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 18b10ac7caf86b0401616b99fb38a7f0fc3c5a5c
Author: Martin Desruisseaux
AuthorDate: Wed Sep 16 19:53:59 2020 +0200
Enable optimization in `TranslationTransform` which were missed.
---
.../transform/AbstractLinearTransform.java | 40 +++++---
.../operation/transform/CopyTransform.java | 112 +++++++++------------
.../operation/transform/ProjectiveTransform.java | 9 +-
.../operation/transform/TranslationTransform.java | 32 +++++-
4 files changed, 112 insertions(+), 81 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 84335d7..1ca6a39 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
@@ -44,7 +44,7 @@ import org.opengis.util.FactoryException;
*
*
* @author Martin Desruisseaux (Geomatys)
- * @version 1.0
+ * @version 1.1
* @since 0.6
* @module
*/
@@ -58,6 +58,8 @@ abstract class AbstractLinearTransform extends AbstractMathTransform implements
* The inverse transform, or {@code null} if not yet created.
* This field is part of the serialization form in order to avoid rounding errors if a user
* asks for the inverse of the inverse (i.e. the original transform) after deserialization.
+ *
+ * @see #inverse()
*/
volatile LinearTransform inverse;
@@ -126,7 +128,8 @@ abstract class AbstractLinearTransform extends AbstractMathTransform implements
}
/**
- * Creates the inverse transform of this object.
+ * Returns the inverse transform of this object.
+ * This method invokes {@link #createInverse()} when first needed, then caches the result.
*/
@Override
@SuppressWarnings("DoubleCheckedLocking") // Okay since 'inverse' is volatile.
@@ -136,19 +139,7 @@ abstract class AbstractLinearTransform extends AbstractMathTransform implements
synchronized (this) {
inv = inverse;
if (inv == null) {
- /*
- * Should never be the identity transform at this point (except during tests) because
- * MathTransforms.linear(…) should never instantiate this class in the identity case.
- * But we check anyway as a paranoiac safety.
- */
- if (isIdentity()) {
- inv = this;
- } else {
- inv = MathTransforms.linear(Matrices.inverse(this));
- if (inv instanceof AbstractLinearTransform) {
- ((AbstractLinearTransform) inv).inverse = this;
- }
- }
+ inv = createInverse();
inverse = inv;
}
}
@@ -157,6 +148,25 @@ abstract class AbstractLinearTransform extends AbstractMathTransform implements
}
/**
+ * Invoked by {@link #inverse()} the first time that the inverse transform needs to be computed.
+ */
+ LinearTransform createInverse() throws NoninvertibleTransformException {
+ /*
+ * Should never be the identity transform at this point (except during tests) because
+ * MathTransforms.linear(…) should never instantiate this class in the identity case.
+ * But we check anyway as a paranoiac safety.
+ */
+ if (isIdentity()) {
+ return this;
+ }
+ final LinearTransform inv = MathTransforms.linear(Matrices.inverse(this));
+ if (inv instanceof AbstractLinearTransform) {
+ ((AbstractLinearTransform) inv).inverse = this;
+ }
+ return inv;
+ }
+
+ /**
* Returns the parameter descriptors for this math transform.
*
* @return {@inheritDoc}
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CopyTransform.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CopyTransform.java
index edf2ee7..c5c25e6 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CopyTransform.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CopyTransform.java
@@ -19,7 +19,6 @@ package org.apache.sis.referencing.operation.transform;
import java.util.Arrays;
import org.opengis.geometry.DirectPosition;
import org.opengis.referencing.operation.Matrix;
-import org.opengis.referencing.operation.NoninvertibleTransformException;
import org.apache.sis.referencing.operation.matrix.MatrixSIS;
import org.apache.sis.referencing.operation.matrix.Matrices;
@@ -36,7 +35,7 @@ import org.apache.sis.referencing.operation.matrix.Matrices;
* an {@link java.awt.geom.AffineTransform} for every 2D affine conversions.
*
* @author Martin Desruisseaux (Geomatys)
- * @version 0.7
+ * @version 1.1
* @since 0.5
* @module
*/
@@ -326,72 +325,61 @@ final class CopyTransform extends AbstractLinearTransform {
}
/**
- * Creates the inverse transform of this object.
+ * Invoked by {@link #inverse()} the first time that the inverse transform needs to be computed.
*/
@Override
- @SuppressWarnings("DoubleCheckedLocking") // Okay since 'inverse' is volatile.
- public LinearTransform inverse() throws NoninvertibleTransformException {
- LinearTransform inv = inverse;
- if (inv == null) {
- synchronized (this) {
- inv = inverse;
- if (inv == null) {
- /*
- * Note: no need to perform the following check at this point because MathTransforms.linear(…)
- * should never instantiate this class in the identity case and because we perform an
- * equivalent check later anyway.
- *
- * if (isIdentity()) {
- * inverse = this;
- * } else { ... }
- */
- final int srcDim = this.srcDim;
- final int dstDim = indices.length;
- final int[] reverse = new int[srcDim];
- Arrays.fill(reverse, -1);
- for (int i=dstDim; --i>=0;) {
- reverse[indices[i]] = i;
- }
- /*
- * Check if there is any unassigned dimension. In such case,
- * delegates to the generic ProjectiveTransform with a matrix
- * which set the missing values to NaN.
- */
- for (int j=srcDim; --j>=0;) {
- if (reverse[j] < 0) {
- final MatrixSIS matrix = Matrices.createZero(srcDim + 1, dstDim + 1);
- for (j=0; j= 0) {
- matrix.setElement(j, i, 1);
- } else {
- matrix.setElement(j, dstDim, Double.NaN);
- }
- }
- matrix.setElement(srcDim, dstDim, 1);
- inv = MathTransforms.linear(matrix);
- if (inv instanceof AbstractLinearTransform) {
- ((AbstractLinearTransform) inv).inverse = this;
- }
- inverse = inv;
- return inv;
- }
- }
- /*
- * At this point, we know that we can create the inverse transform.
- * If this transform is the identity transform or an anti-diagonal matrix except last row
- * (e.g. matrix used for swapping axis order), then the old and new arrays would be equal.
- */
- CopyTransform copyInverse = this;
- if (!Arrays.equals(reverse, indices)) {
- copyInverse = new CopyTransform(indices.length, reverse);
- copyInverse.inverse = this;
+ final LinearTransform createInverse() {
+ /*
+ * Note: no need to perform the following check at this point because MathTransforms.linear(…)
+ * should never instantiate this class in the identity case and because we perform an
+ * equivalent check later anyway.
+ *
+ * if (isIdentity()) {
+ * inverse = this;
+ * } else { ... }
+ */
+ final int srcDim = this.srcDim;
+ final int dstDim = indices.length;
+ final int[] reverse = new int[srcDim];
+ Arrays.fill(reverse, -1);
+ for (int i=dstDim; --i>=0;) {
+ reverse[indices[i]] = i;
+ }
+ /*
+ * Check if there is any unassigned dimension. In such case,
+ * delegates to the generic ProjectiveTransform with a matrix
+ * which set the missing values to NaN.
+ */
+ for (int j=srcDim; --j>=0;) {
+ if (reverse[j] < 0) {
+ final MatrixSIS matrix = Matrices.createZero(srcDim + 1, dstDim + 1);
+ for (j=0; j= 0) {
+ matrix.setElement(j, i, 1);
+ } else {
+ matrix.setElement(j, dstDim, Double.NaN);
}
- inverse = inv = copyInverse;
}
+ matrix.setElement(srcDim, dstDim, 1);
+ final LinearTransform inv = MathTransforms.linear(matrix);
+ if (inv instanceof AbstractLinearTransform) {
+ ((AbstractLinearTransform) inv).inverse = this;
+ }
+ return inv;
}
}
- return inv;
+ /*
+ * At this point, we know that we can create the inverse transform.
+ * If this transform is the identity transform or an anti-diagonal matrix except last row
+ * (e.g. matrix used for swapping axis order), then the old and new arrays would be equal.
+ */
+ CopyTransform copyInverse = this;
+ if (!Arrays.equals(reverse, indices)) {
+ copyInverse = new CopyTransform(indices.length, reverse);
+ copyInverse.inverse = this;
+ }
+ return copyInverse;
}
/**
diff --git a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ProjectiveTransform.java b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ProjectiveTransform.java
index 7516f1f..5dc40ff 100644
--- a/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ProjectiveTransform.java
+++ b/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ProjectiveTransform.java
@@ -113,11 +113,14 @@ class ProjectiveTransform extends AbstractLinearTransform implements ExtendedPre
*/
boolean isScale = true; // ScaleTransform accepts non-square matrix.
boolean isTranslation = (numRow == numCol); // TranslationTransform is restricted to square matrix.
+ final int lastColumn = numCol - 1;
for (int i=0; i
*
* @author Martin Desruisseaux (Geomatys)
- * @version 1.0
+ * @version 1.1
*
* @see SIS-176
*
@@ -75,6 +75,28 @@ final class TranslationTransform extends AbstractLinearTransform implements Exte
}
/**
+ * Creates a transform as the inverse of the given transform.
+ */
+ private TranslationTransform(final TranslationTransform other) {
+ offsets = negate(other.offsets);
+ errors = negate(other.errors);
+ inverse = other;
+ }
+
+ /**
+ * Returns a new array with negative values of given array (can be {@code null}).
+ */
+ private static double[] negate(double[] array) {
+ if (array != null) {
+ array = array.clone();
+ for (int i=0; i