sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1724531 [5/13] - in /sis/trunk: ./ application/sis-console/src/main/artifact/bin/ application/sis-console/src/main/artifact/log/ application/sis-console/src/main/java/org/apache/sis/console/ core/sis-build-helper/src/main/java/org/apache/s...
Date Wed, 13 Jan 2016 23:59:41 GMT
Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/GeneralMatrix.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/GeneralMatrix.java?rev=1724531&r1=1724530&r2=1724531&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/GeneralMatrix.java
[UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/GeneralMatrix.java
[UTF-8] Wed Jan 13 23:59:38 2016
@@ -36,7 +36,7 @@ import org.apache.sis.internal.referenci
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.4
- * @version 0.5
+ * @version 0.7
  * @module
  *
  * @see Matrices#createDiagonal(int, int)
@@ -172,27 +172,6 @@ class GeneralMatrix extends MatrixSIS im
     }
 
     /**
-     * Copies the elements of the given matrix in the given array.
-     * This method ignores the error terms, if any.
-     *
-     * @param matrix   The matrix to copy.
-     * @param numRow   The number of rows to copy (usually {@code matrix.getNumRow()}).
-     * @param numCol   The number of columns to copy (usually {@code matrix.getNumCol()}).
-     * @param elements Where to copy the elements.
-     */
-    private static void getElements(final Matrix matrix, final int numRow, final int numCol,
final double[] elements) {
-        if (matrix instanceof MatrixSIS) {
-            ((MatrixSIS) matrix).getElements(elements);
-        } else {
-            for (int k=0,j=0; j<numRow; j++) {
-                for (int i=0; i<numCol; i++) {
-                    elements[k++] = matrix.getElement(j, i);
-                }
-            }
-        }
-    }
-
-    /**
      * Infers all {@link DoubleDouble#error} with a default values inferred from {@link DoubleDouble#value}.
      * For example if a matrix element is exactly 3.141592653589793, there is good chances
that the user's
      * intend was to specify the {@link Math#PI} value, in which case this method will infer
that we would
@@ -479,6 +458,32 @@ class GeneralMatrix extends MatrixSIS im
     }
 
     /**
+     * Sets this matrix to the values of another matrix. This method overrides the default
implementation with a more
+     * efficient implementation in the particular case where the other matrix is an instance
of {@code GeneralMatrix}.
+     *
+     * @param matrix  The matrix to copy.
+     * @throws MismatchedMatrixSizeException if the given matrix has a different size than
this matrix.
+     *
+     * @since 0.7
+     */
+    @Override
+    public void setMatrix(final Matrix matrix) throws MismatchedMatrixSizeException {
+        if (matrix instanceof GeneralMatrix) {
+            final GeneralMatrix gm = (GeneralMatrix) matrix;
+            ensureSizeMatch(numRow, numCol, matrix);
+            final int length = gm.elements.length;
+            if (elements.length <= length) {
+                System.arraycopy(gm.elements, 0, elements, 0, elements.length);
+            } else {
+                System.arraycopy(gm.elements, 0, elements, 0, length);
+                inferErrors(elements);
+            }
+        } else {
+            super.setMatrix(matrix);
+        }
+    }
+
+    /**
      * {@inheritDoc}
      *
      * <p>This method does not check the error terms, because those terms are not visible
to the user

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrices.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrices.java?rev=1724531&r1=1724530&r2=1724531&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrices.java
[UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrices.java
[UTF-8] Wed Jan 13 23:59:38 2016
@@ -224,7 +224,7 @@ public final class Matrices extends Stat
      * Argument validity shall be verified by the caller.
      *
      * @param useEnvelopes {@code true} if source and destination envelopes shall be taken
in account.
-     *        If {@code false}, then source and destination envelopes will be ignored and
may be null.
+     *        If {@code false}, then source and destination envelopes will be ignored and
can be null.
      */
     @SuppressWarnings("null")
     private static MatrixSIS createTransform(final Envelope srcEnvelope, final AxisDirection[]
srcAxes,
@@ -537,7 +537,7 @@ public final class Matrices extends Stat
      * @throws IllegalArgumentException if a value of {@code selectedDimensions} is lower
than 0
      *         or not smaller than {@code sourceDimensions}.
      *
-     * @see org.apache.sis.referencing.operation.transform.MathTransforms#dimensionFilter(int,
int[])
+     * @see org.apache.sis.referencing.operation.transform.TransformSeparator
      */
     public static MatrixSIS createDimensionSelect(final int sourceDimensions, final int[]
selectedDimensions) {
         final int numTargetDim = selectedDimensions.length;
@@ -714,7 +714,7 @@ public final class Matrices extends Stat
      */
     public static MatrixSIS unmodifiable(final Matrix matrix) {
         if (matrix == null || matrix instanceof UnmodifiableMatrix) {
-            return (UnmodifiableMatrix) matrix;
+            return (MatrixSIS) matrix;
         } else {
             return new UnmodifiableMatrix(matrix);
         }
@@ -915,6 +915,7 @@ public final class Matrices extends Stat
             case BY_CONTRACT:     // Fall through
             case IGNORE_METADATA: return equals(m1, m2, 0, false);
             case DEBUG:           // Fall through
+            case ALLOW_VARIANT:   // Fall through
             case APPROXIMATIVE:   return equals(m1, m2, Numerics.COMPARISON_THRESHOLD, true);
             default: throw new IllegalArgumentException(Errors.format(
                     Errors.Keys.UnknownEnumValue_2, ComparisonMode.class, mode));

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrix1.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrix1.java?rev=1724531&r1=1724530&r2=1724531&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrix1.java
[UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrix1.java
[UTF-8] Wed Jan 13 23:59:38 2016
@@ -117,7 +117,7 @@ public final class Matrix1 extends Matri
         if (matrix == null || matrix instanceof Matrix1) {
             return (Matrix1) matrix;
         }
-        ensureSizeMatch(SIZE, matrix);
+        ensureSizeMatch(SIZE, SIZE, matrix);
         return new Matrix1(matrix);
     }
 

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrix2.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrix2.java?rev=1724531&r1=1724530&r2=1724531&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrix2.java
[UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrix2.java
[UTF-8] Wed Jan 13 23:59:38 2016
@@ -127,7 +127,7 @@ public final class Matrix2 extends Matri
         if (matrix == null || matrix instanceof Matrix2) {
             return (Matrix2) matrix;
         }
-        ensureSizeMatch(SIZE, matrix);
+        ensureSizeMatch(SIZE, SIZE, matrix);
         return new Matrix2(matrix);
     }
 

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrix3.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrix3.java?rev=1724531&r1=1724530&r2=1724531&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrix3.java
[UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrix3.java
[UTF-8] Wed Jan 13 23:59:38 2016
@@ -139,7 +139,7 @@ public final class Matrix3 extends Matri
         if (matrix == null || matrix instanceof Matrix3) {
             return (Matrix3) matrix;
         }
-        ensureSizeMatch(SIZE, matrix);
+        ensureSizeMatch(SIZE, SIZE, matrix);
         return new Matrix3(matrix);
     }
 

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrix4.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrix4.java?rev=1724531&r1=1724530&r2=1724531&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrix4.java
[UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrix4.java
[UTF-8] Wed Jan 13 23:59:38 2016
@@ -157,7 +157,7 @@ public final class Matrix4 extends Matri
         if (matrix == null || matrix instanceof Matrix4) {
             return (Matrix4) matrix;
         }
-        ensureSizeMatch(SIZE, matrix);
+        ensureSizeMatch(SIZE, SIZE, matrix);
         return new Matrix4(matrix);
     }
 

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/MatrixSIS.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/MatrixSIS.java?rev=1724531&r1=1724530&r2=1724531&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/MatrixSIS.java
[UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/MatrixSIS.java
[UTF-8] Wed Jan 13 23:59:38 2016
@@ -20,6 +20,7 @@ import java.util.Arrays;
 import java.io.Serializable;
 import java.awt.geom.AffineTransform;   // For javadoc
 import org.opengis.referencing.operation.Matrix;
+import org.apache.sis.internal.referencing.ExtendedPrecisionMatrix;
 import org.apache.sis.internal.util.DoubleDouble;
 import org.apache.sis.internal.util.Numerics;
 import org.apache.sis.util.ArgumentChecks;
@@ -87,25 +88,26 @@ public abstract class MatrixSIS implemen
     }
 
     /**
-     * Ensures that the given matrix is a square matrix having the given dimension.
+     * Ensures that the given matrix has the given dimension.
      * This is a convenience method for subclasses.
      */
-    static void ensureSizeMatch(final int size, final Matrix matrix) {
-        final int numRow = matrix.getNumRow();
-        final int numCol = matrix.getNumCol();
-        if (numRow != size || numCol != size) {
-            final Integer n = size;
+    static void ensureSizeMatch(final int numRow, final int numCol, final Matrix matrix)
+            throws MismatchedMatrixSizeException
+    {
+        final int othRow = matrix.getNumRow();
+        final int othCol = matrix.getNumCol();
+        if (numRow != othRow || numCol != othCol) {
             throw new MismatchedMatrixSizeException(Errors.format(
-                    Errors.Keys.MismatchedMatrixSize_4, n, n, numRow, numCol));
+                    Errors.Keys.MismatchedMatrixSize_4, numRow, numCol, othRow, othCol));
         }
     }
 
     /**
-     * Ensures that the number of rows of the given matrix matches the given value.
+     * Ensures that the number of rows of a given matrix matches the given value.
      * This is a convenience method for {@link #multiply(Matrix)} implementations.
      *
      * @param expected The expected number of rows.
-     * @param matrix   The matrix to verify.
+     * @param actual   The actual number of rows in the matrix to verify.
      * @param numCol   The number of columns to report in case of errors. This is an arbitrary
      *                 value and have no incidence on the verification performed by this
method.
      */
@@ -214,6 +216,27 @@ public abstract class MatrixSIS implemen
     }
 
     /**
+     * Copies the elements of the given matrix in the given array.
+     * This method ignores the error terms, if any.
+     *
+     * @param matrix   The matrix to copy.
+     * @param numRow   {@code matrix.getNumRow()}.
+     * @param numCol   {@code matrix.getNumCol()}.
+     * @param elements Where to copy the elements.
+     */
+    static void getElements(final Matrix matrix, final int numRow, final int numCol, final
double[] elements) {
+        if (matrix instanceof MatrixSIS) {
+            ((MatrixSIS) matrix).getElements(elements);
+        } else {
+            for (int k=0,j=0; j<numRow; j++) {
+                for (int i=0; i<numCol; i++) {
+                    elements[k++] = matrix.getElement(j, i);
+                }
+            }
+        }
+    }
+
+    /**
      * Sets all matrix elements from a flat, row-major (column indices vary fastest) array.
      * The array length shall be <code>{@linkplain #getNumRow()} * {@linkplain #getNumCol()}</code>.
      *
@@ -226,6 +249,47 @@ public abstract class MatrixSIS implemen
     public abstract void setElements(final double[] elements);
 
     /**
+     * Sets this matrix to the values of another matrix.
+     * The given matrix must have the same size.
+     *
+     * @param matrix  The matrix to copy.
+     * @throws MismatchedMatrixSizeException if the given matrix has a different size than
this matrix.
+     *
+     * @since 0.7
+     */
+    public void setMatrix(final Matrix matrix) throws MismatchedMatrixSizeException {
+        ArgumentChecks.ensureNonNull("matrix", matrix);
+        final int numRow = getNumRow();
+        final int numCol = getNumCol();
+        ensureSizeMatch(numRow, numCol, matrix);
+        final int count = numRow * numCol;
+        final double[] elements;
+        /*
+         * If both matrices use extended precision, the elements array will have twice the
expected length
+         * with the matrix values in the first half and the error terms in the second half.
 If we want to
+         * preserve the extended precision, we have to transfer the values between the two
matrices with a
+         * DoubleDouble object.
+         */
+        if (isExtendedPrecision() && matrix instanceof ExtendedPrecisionMatrix) {
+            elements = ((ExtendedPrecisionMatrix) matrix).getExtendedElements();
+            if (elements.length > count) {
+                final DoubleDouble t = new DoubleDouble();
+                for (int i=0; i<count; i++) {
+                    t.value = elements[i];
+                    t.error = elements[i + count];
+                    set(i / numCol, i % numCol, t);
+                }
+                return;
+            }
+        } else {
+            // Fallback for matrices that do not use extended precision.
+            elements = new double[count];
+            getElements(matrix, numRow, numCol, elements);
+        }
+        setElements(elements);
+    }
+
+    /**
      * Returns {@code true} if this matrix uses extended precision.
      */
     boolean isExtendedPrecision() {

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/NormalizedProjection.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/NormalizedProjection.java?rev=1724531&r1=1724530&r2=1724531&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/NormalizedProjection.java
[UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/projection/NormalizedProjection.java
[UTF-8] Wed Jan 13 23:59:38 2016
@@ -72,7 +72,7 @@ import org.opengis.referencing.Reference
  *
  *   <li>On output, the {@link #transform(double[],int,double[],int,boolean) transform(…)}
method returns
  *   (<var>x</var>, <var>y</var>) values on a sphere or ellipse having
a semi-major axis length (<var>a</var>) of 1.
- *   The multiplication by the scale factor (<var>k</var>₀) and the translation
by false easting (FE) and false
+ *   The multiplication by the scale factor (<var>k₀</var>) and the translation
by false easting (FE) and false
  *   northing (FN) are applied by the {@linkplain ContextualParameters#getMatrix denormalization}
affine transform.</li>
  * </ul>
  *
@@ -98,9 +98,8 @@ import org.opengis.referencing.Reference
  * The first matrix on the left side is for {@linkplain org.apache.sis.referencing.cs.CoordinateSystems#swapAndScaleAxes
  * swapping axes} from (<var>latitude</var>, <var>longitude</var>)
to (<var>longitude</var>, <var>latitude</var>) order.
  * This matrix is shown here for completeness, but is not managed by this projection package.
Axes swapping is managed
- * at a {@linkplain org.apache.sis.referencing.operation.transform.DefaultMathTransformFactory#createBaseToDerived(
- * org.opengis.referencing.cs.CoordinateSystem, org.opengis.referencing.operation.MathTransform,
- * org.opengis.referencing.cs.CoordinateSystem) higher level}.</div>
+ * at a {@linkplain org.apache.sis.referencing.operation.transform.DefaultMathTransformFactory#createParameterizedTransform
+ * higher level}.</div>
  *
  * {@code NormalizedProjection} does not store the above cited parameters (central meridian,
scale factor, <i>etc.</i>)
  * on intend (except indirectly), in order to make clear that those parameters are not used
by subclasses.
@@ -131,7 +130,7 @@ public abstract class NormalizedProjecti
     /**
      * For cross-version compatibility.
      */
-    private static final long serialVersionUID = 1969740225939106310L;
+    private static final long serialVersionUID = -4010883312927645853L;
 
     /**
      * Maximum difference allowed when comparing longitudes or latitudes in radians.
@@ -281,7 +280,7 @@ public abstract class NormalizedProjecti
         CENTRAL_MERIDIAN,
 
         /**
-         * Maps the <cite>scale factor</cite> parameter (symbol: <var>k</var>₀).
+         * Maps the <cite>scale factor</cite> parameter (symbol: <var>k₀</var>).
          * This is a multiplication factor for the (<var>x</var>,<var>y</var>)
values obtained after map projections.
          *
          * <p>Some common names for this parameter are:</p>

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractLinearTransform.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractLinearTransform.java?rev=1724531&r1=1724530&r2=1724531&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractLinearTransform.java
[UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractLinearTransform.java
[UTF-8] Wed Jan 13 23:59:38 2016
@@ -16,14 +16,15 @@
  */
 package org.apache.sis.referencing.operation.transform;
 
+import java.util.Arrays;
 import java.io.Serializable;
 import org.opengis.parameter.ParameterValueGroup;
 import org.opengis.parameter.ParameterDescriptorGroup;
-import org.opengis.referencing.operation.MathTransform;
 import org.opengis.referencing.operation.Matrix;
 import org.opengis.referencing.operation.NoninvertibleTransformException;
 import org.apache.sis.referencing.operation.matrix.Matrices;
 import org.apache.sis.internal.referencing.provider.Affine;
+import org.apache.sis.internal.util.Numerics;
 import org.apache.sis.util.ComparisonMode;
 import org.apache.sis.util.resources.Errors;
 
@@ -55,7 +56,7 @@ abstract class AbstractLinearTransform e
      * 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.
      */
-    MathTransform inverse;
+    volatile LinearTransform inverse;
 
     /**
      * Constructs a transform.
@@ -110,23 +111,31 @@ abstract class AbstractLinearTransform e
      * Creates the inverse transform of this object.
      */
     @Override
-    public synchronized MathTransform inverse() throws NoninvertibleTransformException {
-        if (inverse == 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()) {
-                inverse = this;
-            } else {
-                inverse = MathTransforms.linear(Matrices.inverse(this));
-                if (inverse instanceof AbstractLinearTransform) {
-                    ((AbstractLinearTransform) inverse).inverse = this;
+    @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) {
+                    /*
+                     * 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;
+                        }
+                    }
+                    inverse = inv;
                 }
             }
         }
-        return inverse;
+        return inv;
     }
 
     /**
@@ -161,6 +170,63 @@ abstract class AbstractLinearTransform e
     }
 
     /**
+     * Transforms an array of relative distance vectors. Distance vectors are transformed
without applying
+     * the translation components. The default implementation is not very efficient, but
it should not be
+     * an issue since this method is not invoked often.
+     *
+     * @since 0.7
+     */
+    @Override
+    public void deltaTransform(double[] srcPts, int srcOff, double[] dstPts, int dstOff,
int numPts) {
+        int offFinal = 0;
+        double[] dstFinal = null;
+        final int srcDim, dstDim;
+        int srcInc = srcDim = getSourceDimensions();
+        int dstInc = dstDim = getTargetDimensions();
+        if (srcPts == dstPts) {
+            switch (IterationStrategy.suggest(srcOff, srcDim, dstOff, dstDim, numPts)) {
+                case ASCENDING: {
+                    break;
+                }
+                case DESCENDING: {
+                    srcOff += (numPts - 1) * srcDim;  srcInc = -srcInc;
+                    dstOff += (numPts - 1) * dstDim;  dstInc = -dstInc;
+                    break;
+                }
+                default: {
+                    srcPts = Arrays.copyOfRange(srcPts, srcOff, srcOff + numPts*srcDim);
+                    srcOff = 0;
+                    break;
+                }
+                case BUFFER_TARGET: {
+                    dstFinal = dstPts; dstPts = new double[numPts * dstInc];
+                    offFinal = dstOff; dstOff = 0;
+                    break;
+                }
+            }
+        }
+        final double[] buffer = new double[dstDim];
+        while (--numPts >= 0) {
+            for (int j=0; j<dstDim; j++) {
+                double sum = 0;
+                for (int i=0; i<srcDim; i++) {
+                    final double e = getElement(j, i);
+                    if (e != 0) {   // See the comment in ProjectiveTransform for the purpose
of this test.
+                        sum += srcPts[srcOff + i] * e;
+                    }
+                }
+                buffer[j] = sum;
+            }
+            System.arraycopy(buffer, 0, dstPts, dstOff, dstDim);
+            srcOff += srcInc;
+            dstOff += dstInc;
+        }
+        if (dstFinal != null) {
+            System.arraycopy(dstPts, 0, dstFinal, offFinal, dstPts.length);
+        }
+    }
+
+    /**
      * Compares this math transform with an object which is known to be of the same class.
      * Implementors can safely cast the {@code object} argument to their subclass.
      *
@@ -187,19 +253,77 @@ abstract class AbstractLinearTransform e
         if (object == this) { // Slight optimization
             return true;
         }
-        if (object != null) {
-            if (getClass() == object.getClass() && !mode.isApproximative()) {
-                return equalsSameClass(object);
+        if (object == null) {
+            return false;
+        }
+        final boolean isApproximative = mode.isApproximative();
+        if (!isApproximative && getClass() == object.getClass()) {
+            if (!equalsSameClass(object)) {
+                return false;
             }
-            if (mode != ComparisonMode.STRICT) {
-                if (object instanceof LinearTransform) {
-                    return Matrices.equals(this, ((LinearTransform) object).getMatrix(),
mode);
-                } else if (object instanceof Matrix) {
-                    return Matrices.equals(this, (Matrix) object, mode);
-                }
+        } else if (mode == ComparisonMode.STRICT) {
+            return false;
+        } else {
+            final Matrix m;
+            if (object instanceof LinearTransform) {
+                m = ((LinearTransform) object).getMatrix();
+            } else if (object instanceof Matrix) {
+                m = (Matrix) object;
+            } else {
+                return false;
+            }
+            if (!Matrices.equals(this, m, mode)) {
+                return false;
+            }
+        }
+        /*
+         * At this point the transforms are considered equal. In theory we would not need
to check
+         * the inverse transforms since if A and B are equal, then A⁻¹ and B⁻¹ should
be equal too.
+         * However in Apache SIS this is not exactly true because computation of inverse
transforms
+         * avoid NaN values in some circumstances. For example the inverse of a 2×3 matrix
normally
+         * sets the "new" dimensions to NaN, but in the particular case where the transform
is used
+         * for a "Geographic 2D to 3D" conversion it will rather set the new dimensions to
zero. So
+         * A⁻¹ and B⁻¹ may differ in their "NaN versus 0" values even if A and B are
equal.
+         *
+         * Opportunistically, the comparison of inverse transforms in approximative mode
also ensures
+         * that we are below the tolerance threshold not only for this matrix, but for the
inverse one
+         * as well.
+         */
+        if (object instanceof AbstractLinearTransform) {
+            /*
+             * If the 'inverse' matrix was not computed in any of the transforms being compared
+             * (i.e. if 'this.inverse' and 'object.inverse' are both null), then assume that
the
+             * two transforms will compute their inverse in the same way. The intend is to
avoid
+             * to trig the inverse transform computation.
+             *
+             * Note that this code requires the 'inverse' fields to be volatile
+             * (otherwise we would need to synchronize).
+             */
+            if (inverse == ((AbstractLinearTransform) object).inverse) {
+                return true;
+            }
+        }
+        /*
+         * Get the matrices of inverse transforms. In the following code 'null' is really
the intended
+         * value for non-invertible matrices because the Matrices.equals(…) methods accept
null values,
+         * so we are okay to ignore NoninvertibleTransformException in this particular case.
+         */
+        Matrix mt = null, mo = null;
+        try {
+            mt = inverse().getMatrix();
+        } catch (NoninvertibleTransformException e) {
+            // Leave 'mt' to null.
+        }
+        try {
+            if (object instanceof LinearTransform) {
+                mo = ((LinearTransform) object).inverse().getMatrix();
+            } else if (object instanceof Matrix) {
+                mo = Matrices.inverse((Matrix) object);
             }
+        } catch (NoninvertibleTransformException e) {
+            // Leave 'mo' to null.
         }
-        return false;
+        return Matrices.equals(mt, mo, isApproximative ? Numerics.COMPARISON_THRESHOLD :
0, isApproximative);
     }
 
     /**

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractMathTransform.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractMathTransform.java?rev=1724531&r1=1724530&r2=1724531&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractMathTransform.java
[UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/AbstractMathTransform.java
[UTF-8] Wed Jan 13 23:59:38 2016
@@ -358,8 +358,8 @@ public abstract class AbstractMathTransf
      * transforming many points. The supplied array of ordinal values will contain packed
ordinal values.
      *
      * <div class="note"><b>Example:</b> if the source dimension is 3,
then the ordinates will be packed in this order:
-     * (<var>x<sub>0</sub></var>,<var>y<sub>0</sub></var>,<var>z<sub>0</sub></var>,
-     *  <var>x<sub>1</sub></var>,<var>y<sub>1</sub></var>,<var>z<sub>1</sub></var>
…).
+     * (<var>x₀</var>,<var>y₀</var>,<var>z₀</var>,
+     *  <var>x₁</var>,<var>y₁</var>,<var>z₁</var>
…).
      * </div>
      *
      * The default implementation invokes {@link #transform(double[], int, double[], int,
boolean)} in a loop,
@@ -568,7 +568,7 @@ public abstract class AbstractMathTransf
                 }
             }
             for (int i=0; i<srcStop; i++) {
-                buffer[bufferedSrcOff + i] = (double) srcPts[srcOff + i];
+                buffer[bufferedSrcOff + i] = srcPts[srcOff + i];
             }
             assert !IterationStrategy.suggest(bufferedSrcOff, dimSource, 0, dimTarget, numBufferedPts).needBuffer;
             try {
@@ -709,7 +709,7 @@ public abstract class AbstractMathTransf
                 dstLength = numPts * dimTarget;
             }
             for (int i=0; i<srcLength; i++) {
-                buffer[i] = (double) srcPts[srcOff++];
+                buffer[i] = srcPts[srcOff++];
             }
             try {
                 transform(buffer, 0, dstPts, dstOff, numBufferedPts);

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ContextualParameters.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ContextualParameters.java?rev=1724531&r1=1724530&r2=1724531&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ContextualParameters.java
[UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/ContextualParameters.java
[UTF-8] Wed Jan 13 23:59:38 2016
@@ -160,7 +160,7 @@ public class ContextualParameters extend
          * Inverse of the {@link #NORMALIZATION} matrix.
          * For example in a map projection, this matrix is typically (but not necessarily)
as below:
          *
-         * <center>{@include formulas.html#DeormalizeGeographic}</center>
+         * <center>{@include formulas.html#DenormalizeGeographic}</center>
          */
         INVERSE_NORMALIZATION,
 
@@ -477,7 +477,7 @@ public class ContextualParameters extend
      * the denormalization matrix with the following matrix. This will have the effect of
applying the conversion
      * described above after the non-linear kernel operation:</p>
      *
-     * <center>{@include formulas.html#DeormalizeGeographic}</center>
+     * <center>{@include formulas.html#DenormalizeGeographic}</center>
      *
      * @param  λ0 Longitude of the central meridian, in degrees.
      * @return The denormalization affine transform as a matrix.
@@ -514,7 +514,6 @@ public class ContextualParameters extend
      *
      * @see org.apache.sis.referencing.operation.projection.NormalizedProjection#createMapProjection(MathTransformFactory)
      */
-    @SuppressWarnings("AssignmentToForLoopParameter")
     public synchronized MathTransform completeTransform(final MathTransformFactory factory,
final MathTransform kernel)
             throws FactoryException
     {
@@ -530,6 +529,9 @@ public class ContextualParameters extend
         Matrix m;
         if ((m = MathTransforms.getMatrix(n)) != null)   normalize = m;
         if ((m = MathTransforms.getMatrix(d)) != null) denormalize = m;
+        if (kernel == null) {   // Undocumented feature useful for MolodenskyTransform constructor.
+            return null;
+        }
         return factory.createConcatenatedTransform(factory.createConcatenatedTransform(n,
kernel), d);
     }
 

Modified: sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CopyTransform.java
URL: http://svn.apache.org/viewvc/sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CopyTransform.java?rev=1724531&r1=1724530&r2=1724531&view=diff
==============================================================================
--- sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CopyTransform.java
[UTF-8] (original)
+++ sis/trunk/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/transform/CopyTransform.java
[UTF-8] Wed Jan 13 23:59:38 2016
@@ -19,7 +19,6 @@ package org.apache.sis.referencing.opera
 import java.util.Arrays;
 import org.opengis.geometry.DirectPosition;
 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.MatrixSIS;
 import org.apache.sis.referencing.operation.matrix.Matrices;
@@ -330,61 +329,69 @@ final class CopyTransform extends Abstra
      * Creates the inverse transform of this object.
      */
     @Override
-    public synchronized MathTransform inverse() throws NoninvertibleTransformException {
-        if (inverse == null) {
-            /*
-             * Note: no need to perform the following check as 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<srcDim; j++) {      // Okay to reuse 'j' since the outer
loop will not continue.
-                        final int i = reverse[j];
-                        if (i >= 0) {
-                            matrix.setElement(j, i, 1);
-                        } else {
-                            matrix.setElement(j, dstDim, Double.NaN);
+    @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<srcDim; j++) {      // Okay to reuse 'j' since
the outer loop will not continue.
+                                final int i = reverse[j];
+                                if (i >= 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;
                         }
                     }
-                    matrix.setElement(srcDim, dstDim, 1);
-                    inverse = MathTransforms.linear(matrix);
-                    if (inverse instanceof AbstractLinearTransform) {
-                        ((AbstractLinearTransform) inverse).inverse = this;
+                    /*
+                     * At this point, we know that we can create the inverse transform.
+                     * If this transform is the identity transform (we should never happen,
+                     * but we are paranoiac), 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 inverse;
+                    inverse = inv = copyInverse;
                 }
             }
-            /*
-             * At this point, we know that we can create the inverse transform.
-             * If this transform is the identity transform (we should never happen,
-             * but we are paranoiac), 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;
-            }
-            inverse = copyInverse;
         }
-        return inverse;
+        return inv;
     }
 
     /**




Mime
View raw message