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
The following commit(s) were added to refs/heads/geoapi-4.0 by this push:
new 52f7098f12 Cache the inverse operation. The main intend is to avoid
information lost when the inverse of the inverse is later requested.
52f7098f12 is described below
commit 52f7098f12d7cbd73edccb4d9b08ce86f7d7b4d3
Author: Martin Desruisseaux <[email protected]>
AuthorDate: Wed Jan 10 14:22:11 2024 +0100
Cache the inverse operation. The main intend is to avoid information lost
when the inverse of the inverse is later requested.
---
.../operation/AbstractCoordinateOperation.java | 49 +++++++++++++++++++++-
.../operation/CoordinateOperationFinder.java | 7 +---
.../operation/CoordinateOperationRegistry.java | 17 ++++++--
.../operation/DefaultConcatenatedOperation.java | 10 ++++-
.../sis/referencing/util/CoordinateOperations.java | 14 +++++++
.../bind/referencing/CC_CoordinateOperation.java | 4 +-
6 files changed, 87 insertions(+), 14 deletions(-)
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java
index d957fa3dc7..3fe9667080 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/AbstractCoordinateOperation.java
@@ -102,7 +102,7 @@ import static org.apache.sis.util.Utilities.deepEquals;
* synchronization.
*
* @author Martin Desruisseaux (IRD, Geomatys)
- * @version 1.4
+ * @version 1.5
* @since 0.6
*/
@XmlType(name = "AbstractCoordinateOperationType", propOrder = {
@@ -208,6 +208,19 @@ public class AbstractCoordinateOperation extends
AbstractIdentifiedObject implem
*/
private transient Set<Integer> wrapAroundChanges;
+ /**
+ * The inverse of this coordinate operation, computed when first needed.
This is stored for making
+ * possible to find the original operation when the inverse of an inverse
operation is requested.
+ * Serialized for avoiding information lost if the inverse is requested
after deserialization.
+ *
+ * <p>This field is not formally part of coordinate operation definition,
+ * so it is not compared by {@link #equals(Object, ComparisonMode)}.</p>
+ *
+ * @see #getCachedInverse(CoordinateOperation)
+ */
+ @SuppressWarnings("serial") // Most SIS implementations are
serializable.
+ private volatile CoordinateOperation inverse;
+
/**
* Creates a new coordinate operation initialized from the given
properties.
* It is caller's responsibility to:
@@ -329,6 +342,7 @@ public class AbstractCoordinateOperation extends
AbstractIdentifiedObject implem
* are consistent with {@link #transform} input and output dimensions.
*/
final void checkDimensions(final Map<String,?> properties) {
+ @SuppressWarnings("LocalVariableHidesMemberVariable")
final MathTransform transform = this.transform; //
Protect from changes.
if (transform != null) {
final int interpDim =
ReferencingUtilities.getDimension(interpolationCRS);
@@ -739,6 +753,38 @@ check: for (int isTarget=0; ; isTarget++) { //
0 == source check; 1
return wrapAroundChanges;
}
+ /**
+ * Returns the inverse of the given coordinate operation, or {@code null}
if unspecified.
+ * This method only checks the cached value and does not compute a new
value if none is present.
+ *
+ * @param forward the operation for which to get the inverse.
+ * @return the cached inverse operation, or {@code null} if none.
+ */
+ static CoordinateOperation getCachedInverse(final CoordinateOperation
forward) {
+ if (forward instanceof AbstractCoordinateOperation) {
+ final CoordinateOperation inverse = ((AbstractCoordinateOperation)
forward).inverse;
+ if (inverse != null) {
+ return inverse;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Caches the inverse of the given coordinate operation.
+ *
+ * @param forward the operation for which to cache the inverse.
+ * @param inverse the inverse operation to cache.
+ */
+ static void setCachedInverse(final CoordinateOperation forward, final
CoordinateOperation inverse) {
+ if (inverse instanceof AbstractCoordinateOperation) {
+ ((AbstractCoordinateOperation) inverse).inverse = forward;
+ }
+ if (forward instanceof AbstractCoordinateOperation) {
+ ((AbstractCoordinateOperation) forward).inverse = inverse;
+ }
+ }
+
/**
* Compares this coordinate operation with the specified object for
equality. If the {@code mode} argument
* is {@link ComparisonMode#STRICT} or {@link ComparisonMode#BY_CONTRACT
BY_CONTRACT}, then all available
@@ -881,6 +927,7 @@ check: for (int isTarget=0; ; isTarget++) { //
0 == source check; 1
protected String formatTo(final Formatter formatter) {
super.formatTo(formatter);
formatter.newLine();
+ @SuppressWarnings("LocalVariableHidesMemberVariable")
final CoordinateReferenceSystem sourceCRS = getSourceCRS();
final CoordinateReferenceSystem targetCRS = getTargetCRS();
final Convention convention = formatter.getConvention();
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/CoordinateOperationFinder.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/CoordinateOperationFinder.java
index 53d1602d2b..05d166c263 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/CoordinateOperationFinder.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/CoordinateOperationFinder.java
@@ -1178,12 +1178,7 @@ public class CoordinateOperationFinder extends
CoordinateOperationRegistry {
* Returns {@code true} if the given operation is non-null and use the
affine operation method.
*/
private static boolean isAffine(final CoordinateOperation operation) {
- if (operation instanceof SingleOperation) {
- if (IdentifiedObjects.isHeuristicMatchForName(((SingleOperation)
operation).getMethod(), Constants.AFFINE)) {
- return true;
- }
- }
- return false;
+ return
IdentifiedObjects.isHeuristicMatchForName(CoordinateOperations.getMethod(operation),
Constants.AFFINE);
}
/**
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java
index 568569454f..8e0ca1307b 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/CoordinateOperationRegistry.java
@@ -721,6 +721,10 @@ class CoordinateOperationRegistry {
* see ISO 19111 for more information).
*/
final CoordinateOperation inverse(final SingleOperation op) throws
NoninvertibleTransformException, FactoryException {
+ CoordinateOperation inverse =
AbstractCoordinateOperation.getCachedInverse(op);
+ if (inverse != null) {
+ return inverse;
+ }
final CoordinateReferenceSystem sourceCRS = op.getSourceCRS();
final CoordinateReferenceSystem targetCRS = op.getTargetCRS();
final MathTransform transform = op.getMathTransform().inverse();
@@ -735,7 +739,9 @@ class CoordinateOperationRegistry {
Class<? extends CoordinateOperation> type = null;
if (op instanceof Transformation) type = Transformation.class;
else if (op instanceof Conversion) type = Conversion.class;
- return createFromMathTransform(properties, targetCRS, sourceCRS,
transform, method, null, type);
+ inverse = createFromMathTransform(properties, targetCRS, sourceCRS,
transform, method, null, type);
+ AbstractCoordinateOperation.setCachedInverse(op, inverse);
+ return inverse;
}
/**
@@ -758,6 +764,10 @@ class CoordinateOperationRegistry {
if (operation instanceof SingleOperation) {
return inverse((SingleOperation) operation);
}
+ CoordinateOperation inverse =
AbstractCoordinateOperation.getCachedInverse(operation);
+ if (inverse != null) {
+ return inverse;
+ }
if (operation instanceof ConcatenatedOperation) {
final CoordinateOperation[] inverted =
getSteps((ConcatenatedOperation) operation, true);
ArraysExt.reverse(inverted);
@@ -766,9 +776,10 @@ class CoordinateOperationRegistry {
if (transform != null) {
properties.put(DefaultConcatenatedOperation.TRANSFORM_KEY,
transform.inverse());
}
- return factory.createConcatenatedOperation(properties, inverted);
+ inverse = factory.createConcatenatedOperation(properties,
inverted);
+ AbstractCoordinateOperation.setCachedInverse(operation, inverse);
}
- return null;
+ return inverse;
}
/**
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java
index 4b434f18f5..8317a2059b 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/operation/DefaultConcatenatedOperation.java
@@ -37,6 +37,7 @@ import org.apache.sis.referencing.IdentifiedObjects;
import
org.apache.sis.referencing.operation.transform.DefaultMathTransformFactory;
import org.apache.sis.referencing.factory.InvalidGeodeticParameterException;
import org.apache.sis.referencing.util.PositionalAccuracyConstant;
+import org.apache.sis.referencing.util.CoordinateOperations;
import org.apache.sis.referencing.internal.Resources;
import org.apache.sis.util.Utilities;
import org.apache.sis.util.ComparisonMode;
@@ -229,7 +230,7 @@ final class DefaultConcatenatedOperation extends
AbstractCoordinateOperation imp
CoordinateReferenceSystem source; // Source CRS of
current iteration.
CoordinateReferenceSystem target = null; // Target CRS of
current and last iteration.
for (int i=0; i<operations.length; i++) {
- final CoordinateOperation op = operations[i];
+ CoordinateOperation op = operations[i];
ArgumentChecks.ensureNonNullElement("operations", i, op);
/*
* Verify consistency of user argument: for each coordinate
operation, the source CRS
@@ -243,10 +244,15 @@ final class DefaultConcatenatedOperation extends
AbstractCoordinateOperation imp
var t = source;
source = target;
target = t;
+ // Inverse the operation only if it produces a more natural
definition.
+ if (CoordinateOperations.getMethod(op) instanceof
InverseOperationMethod) {
+ CoordinateOperation natural = getCachedInverse(op);
+ if (natural != null) op = natural;
+ }
}
if (setSource) {
setSource = false;
- sourceCRS = source;
// Take even if null.
+ sourceCRS = source; // Take even if null.
}
/*
* Now that we have verified the CRS chaining, we should be able
to concatenate the transforms.
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/util/CoordinateOperations.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/util/CoordinateOperations.java
index 127a4f3c26..7653014f84 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/util/CoordinateOperations.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/referencing/util/CoordinateOperations.java
@@ -31,6 +31,7 @@ import org.opengis.referencing.crs.CRSFactory;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.crs.GeneralDerivedCRS;
import org.opengis.referencing.operation.OperationMethod;
+import org.opengis.referencing.operation.SingleOperation;
import org.opengis.referencing.operation.CoordinateOperation;
import org.opengis.referencing.operation.CoordinateOperationFactory;
import org.opengis.referencing.operation.MathTransformFactory;
@@ -138,6 +139,19 @@ public final class CoordinateOperations extends Static {
return new DefaultCoordinateOperationFactory(properties, mtFactory);
}
+ /**
+ * Returns the method of the given coordinate operation, or {@code null}
if none.
+ *
+ * @param operation the operation from which to get the method, or
{@code null}.
+ * @return the coordinate operation method, or {@code null} if none.
+ */
+ public static OperationMethod getMethod(final CoordinateOperation
operation) {
+ if (operation instanceof SingleOperation) {
+ return ((SingleOperation) operation).getMethod();
+ }
+ return null;
+ }
+
/**
* Returns the operation method for the specified name or identifier. The
given argument shall be either a
* method name (e.g. <q>Transverse Mercator</q>) or one of its identifiers
(e.g. {@code "EPSG:9807"}).
diff --git
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/xml/bind/referencing/CC_CoordinateOperation.java
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/xml/bind/referencing/CC_CoordinateOperation.java
index dc56f10b73..0c368c20fc 100644
---
a/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/xml/bind/referencing/CC_CoordinateOperation.java
+++
b/endorsed/src/org.apache.sis.referencing/main/org/apache/sis/xml/bind/referencing/CC_CoordinateOperation.java
@@ -19,8 +19,8 @@ package org.apache.sis.xml.bind.referencing;
import jakarta.xml.bind.annotation.XmlElementRef;
import org.opengis.referencing.operation.CoordinateOperation;
import org.opengis.referencing.operation.PassThroughOperation;
-import org.opengis.referencing.operation.SingleOperation;
import org.apache.sis.xml.bind.gco.PropertyType;
+import org.apache.sis.referencing.util.CoordinateOperations;
import org.apache.sis.referencing.operation.AbstractCoordinateOperation;
@@ -98,7 +98,7 @@ public final class CC_CoordinateOperation extends
PropertyType<CC_CoordinateOper
if (((PassThroughOperation) operation).getOperation() == null) {
incomplete("coordOperation");
}
- } else if ((operation instanceof SingleOperation) &&
((SingleOperation) operation).getMethod() == null) {
+ } else if (CoordinateOperations.getMethod(operation) == null) {
incomplete("method");
}
}