sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject [sis] 03/05: Reduce the amount of transform to inverse when ConcatenatedTransform verify if two transforms are the inverse of each other.
Date Thu, 29 Nov 2018 18:09:19 GMT
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 29e677956ae083a6b4ff19b309dd1200a2b57441
Author: Martin Desruisseaux <martin.desruisseaux@geomatys.com>
AuthorDate: Thu Nov 29 16:17:03 2018 +0100

    Reduce the amount of transform to inverse when ConcatenatedTransform verify if two transforms
are the inverse of each other.
---
 .../transform/AbstractLinearTransform.java         | 13 ++++-
 .../operation/transform/AbstractMathTransform.java | 56 +++++++++++++++++++-
 .../operation/transform/ConcatenatedTransform.java | 61 ++++++++++------------
 .../operation/transform/PassThroughTransform.java  | 17 ++++++
 4 files changed, 113 insertions(+), 34 deletions(-)

diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractLinearTransform.java
b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractLinearTransform.java
index 62b2166..2bc05f3 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractLinearTransform.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractLinearTransform.java
@@ -21,6 +21,7 @@ import java.io.Serializable;
 import org.opengis.parameter.ParameterValueGroup;
 import org.opengis.parameter.ParameterDescriptorGroup;
 import org.opengis.referencing.operation.Matrix;
+import org.opengis.referencing.operation.MathTransform;
 import org.opengis.referencing.operation.NoninvertibleTransformException;
 import org.apache.sis.referencing.operation.matrix.Matrices;
 import org.apache.sis.internal.referencing.provider.Affine;
@@ -41,7 +42,7 @@ import org.apache.sis.util.resources.Errors;
  * </ul>
  *
  * @author  Martin Desruisseaux (Geomatys)
- * @version 0.7
+ * @version 1.0
  * @since   0.6
  * @module
  */
@@ -109,6 +110,16 @@ abstract class AbstractLinearTransform extends AbstractMathTransform
implements
     }
 
     /**
+     * Returns {@code true} if this transform is the inverse of the given transform.
+     * If this method is unsure, it conservatively returns {@code false}.
+     */
+    @Override
+    final boolean isInverseOf(final MathTransform other) {
+        // Skip the check if the other transform is not linear.
+        return (other instanceof LinearTransform) && super.isInverseOf(other);
+    }
+
+    /**
      * Creates the inverse transform of this object.
      */
     @Override
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractMathTransform.java
b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractMathTransform.java
index e4e292d..73e5642 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractMathTransform.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractMathTransform.java
@@ -78,7 +78,7 @@ import static org.apache.sis.util.ArgumentChecks.ensureDimensionMatches;
  * running the same SIS version.
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
- * @version 0.8
+ * @version 1.0
  *
  * @see DefaultMathTransformFactory
  * @see org.apache.sis.referencing.operation.AbstractCoordinateOperation
@@ -791,6 +791,60 @@ public abstract class AbstractMathTransform extends FormattableObject
     }
 
     /**
+     * Returns {@code true} if this transform is the inverse of the given transform.
+     * If this method is unsure, it conservatively returns {@code false}.
+     *
+     * <p>The default implementation invokes {@link #inverse()} and compares the transforms.
+     * Subclasses should override with a more efficient implementation if they can avoid
the
+     * call to {@link #inverse()} (unless that call is cheap).</p>
+     *
+     * @param  other  the transform that may be the inverse of this transform.
+     * @return whether this transform is the inverse of the given transform. If unsure, {@code
false}.
+     */
+    boolean isInverseOf(final MathTransform other) {
+        return inverseEquals(this, other);
+    }
+
+    /**
+     * Returns {@code true} if {@code tr1} is the inverse of {@code tr2}.
+     * If this method is unsure, it conservatively returns {@code false}.
+     * This implementation delegates to {@link #isInverseOf(MathTransform)}
+     * if possible, or to the default implementation otherwise. The transform
+     * that may be inverted is {@code tr1}.
+     */
+    static boolean areInverse(final MathTransform tr1, final MathTransform tr2) {
+        if (tr1 instanceof AbstractMathTransform) {
+            return ((AbstractMathTransform) tr1).isInverseOf(tr2);
+        } else {
+            return inverseEquals(tr1, tr2);
+        }
+    }
+
+    /**
+     * Implementation of {@link #isInverseOf(MathTransform)} for arbitrary math transform.
+     * This method invokes {@link #inverse()} on {@code tr1}.
+     */
+    private static boolean inverseEquals(MathTransform tr1, final MathTransform tr2) {
+        if (tr1.getSourceDimensions() != tr2.getTargetDimensions() ||
+            tr1.getTargetDimensions() != tr2.getSourceDimensions())
+        {
+            return false;
+        }
+        try {
+            tr1 = tr1.inverse();
+        } catch (NoninvertibleTransformException e) {
+            return false;
+        }
+        if (tr1 instanceof LenientComparable) {
+            return ((LenientComparable) tr1).equals(tr2, ComparisonMode.APPROXIMATIVE);
+        }
+        if (tr2 instanceof LenientComparable) {
+            return ((LenientComparable) tr2).equals(tr1, ComparisonMode.APPROXIMATIVE);
+        }
+        return tr1.equals(tr2);
+    }
+
+    /**
      * Concatenates or pre-concatenates in an optimized way this math transform with the
given one, if possible.
      * A new math transform is created to perform the combined transformation.
      * The {@code applyOtherFirst} value determines the transformation order as bellow:
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConcatenatedTransform.java
b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConcatenatedTransform.java
index 0266938..4135bb8 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConcatenatedTransform.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ConcatenatedTransform.java
@@ -38,7 +38,6 @@ import org.apache.sis.internal.metadata.WKTKeywords;
 import org.apache.sis.internal.referencing.Resources;
 import org.apache.sis.internal.system.Semaphores;
 import org.apache.sis.util.Classes;
-import org.apache.sis.util.LenientComparable;
 import org.apache.sis.util.ComparisonMode;
 import org.apache.sis.util.Utilities;
 import org.apache.sis.io.wkt.Convention;
@@ -114,28 +113,6 @@ class ConcatenatedTransform extends AbstractMathTransform implements
Serializabl
     }
 
     /**
-     * Tests if one math transform is the inverse of the other, or approximately the inverse.
-     * Used for {@link #createOptimized(MathTransform, MathTransform, MathTransformFactory)}
implementation.
-     */
-    private static boolean areInverse(final MathTransform tr1, MathTransform tr2) {
-        try {
-            tr2 = tr2.inverse();
-        } catch (NoninvertibleTransformException e) {
-            return false;
-        }
-        if (tr1 == tr2) {
-            return true;
-        }
-        if (tr1 instanceof LenientComparable) {
-            return ((LenientComparable) tr1).equals(tr2, ComparisonMode.APPROXIMATIVE);
-        }
-        if (tr2 instanceof LenientComparable) {
-            return ((LenientComparable) tr2).equals(tr1, ComparisonMode.APPROXIMATIVE);
-        }
-        return tr1.equals(tr2);
-    }
-
-    /**
      * Concatenates the two given transforms.
      * If the concatenation result works with two-dimensional input and output points,
      * then the returned transform will implement {@link MathTransform2D}.
@@ -805,6 +782,20 @@ class ConcatenatedTransform extends AbstractMathTransform implements
Serializabl
     }
 
     /**
+     * Gets the derivative of this transform at a point.
+     *
+     * @param  point  the coordinate point where to evaluate the derivative.
+     * @return the derivative at the specified point (never {@code null}).
+     * @throws TransformException if the derivative can't be evaluated at the specified point.
+     */
+    @Override
+    public Matrix derivative(final DirectPosition point) throws TransformException {
+        final Matrix matrix1 = transform1.derivative(point);
+        final Matrix matrix2 = transform2.derivative(transform1.transform(point, null));
+        return Matrices.multiply(matrix2, matrix1);
+    }
+
+    /**
      * Creates the inverse transform of this object.
      */
     @Override
@@ -822,17 +813,23 @@ class ConcatenatedTransform extends AbstractMathTransform implements
Serializabl
     }
 
     /**
-     * Gets the derivative of this transform at a point.
-     *
-     * @param  point  the coordinate point where to evaluate the derivative.
-     * @return the derivative at the specified point (never {@code null}).
-     * @throws TransformException if the derivative can't be evaluated at the specified point.
+     * Returns {@code true} if this transform is the inverse of the given transform.
+     * If this method is unsure, it conservatively returns {@code false}.
      */
     @Override
-    public Matrix derivative(final DirectPosition point) throws TransformException {
-        final Matrix matrix1 = transform1.derivative(point);
-        final Matrix matrix2 = transform2.derivative(transform1.transform(point, null));
-        return Matrices.multiply(matrix2, matrix1);
+    final boolean isInverseOf(final MathTransform other) {
+        final List<MathTransform> s1 = getSteps();
+        final List<MathTransform> s2 = MathTransforms.getSteps(other);
+        final int size = s1.size();
+        if (s2.size() != size) {
+            return false;
+        }
+        for (int i=0; i<size; i++) {
+            if (!areInverse(s1.get(size-1 - i), s2.get(i))) {
+                return false;
+            }
+        }
+        return true;
     }
 
     /**
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/PassThroughTransform.java
b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/PassThroughTransform.java
index ae1b7f6..bae1e8a 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/PassThroughTransform.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/PassThroughTransform.java
@@ -641,6 +641,23 @@ public class PassThroughTransform extends AbstractMathTransform implements
Seria
     }
 
     /**
+     * Returns {@code true} if this transform is the inverse of the given transform.
+     * If this method is unsure, it conservatively returns {@code false}.
+     */
+    @Override
+    final boolean isInverseOf(final MathTransform other) {
+        if (other instanceof PassThroughTransform) {
+            final PassThroughTransform ps = (PassThroughTransform) other;
+            if (firstAffectedOrdinate == ps.firstAffectedOrdinate &&
+                numTrailingOrdinates  == ps.numTrailingOrdinates)
+            {
+                return areInverse(subTransform, ps.subTransform);
+            }
+        }
+        return false;
+    }
+
+    /**
      * Concatenates or pre-concatenates in an optimized way this transform with the given
transform, if possible.
      * This method applies the following special cases:
      *


Mime
View raw message