sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1738223 - in /sis/branches/JDK8/core/sis-referencing/src: main/java/org/apache/sis/referencing/operation/ main/java/org/apache/sis/referencing/operation/matrix/ test/java/org/apache/sis/referencing/operation/matrix/
Date Fri, 08 Apr 2016 09:30:25 GMT
Author: desruisseaux
Date: Fri Apr  8 09:30:25 2016
New Revision: 1738223

URL: http://svn.apache.org/viewvc?rev=1738223&view=rev
Log:
Add a Matrices.resizeAffine(...) method to be needed for CoordinateOperationFinder.

Modified:
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationInference.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrices.java
    sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/MatrixSIS.java
    sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/MatricesTest.java

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationInference.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationInference.java?rev=1738223&r1=1738222&r2=1738223&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationInference.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/CoordinateOperationInference.java
[UTF-8] Fri Apr  8 09:30:25 2016
@@ -367,7 +367,12 @@ public class CoordinateOperationInferenc
     {
         // Create first the operation that is more at risk to fail.
         final CoordinateOperation step2 = createOperation(sourceCRS.getBaseCRS(), targetCRS);
-        final CoordinateOperation step1 = inverse(sourceCRS.getConversionFromBase());
+        final CoordinateOperation step1;
+        try {
+            step1 = inverse(sourceCRS.getConversionFromBase());
+        } catch (NoninvertibleTransformException exception) {
+            throw new OperationNotFoundException(notFoundMessage(sourceCRS, targetCRS), exception);
+        }
         return concatenate(step1, step2);
     }
 
@@ -392,8 +397,13 @@ public class CoordinateOperationInferenc
     {
         // Create first the operations that are more at risk to fail.
         final CoordinateOperation step2 = createOperation(sourceCRS.getBaseCRS(), targetCRS.getBaseCRS());
-        final CoordinateOperation step1 = inverse(sourceCRS.getConversionFromBase());
         final CoordinateOperation step3 = targetCRS.getConversionFromBase();
+        final CoordinateOperation step1;
+        try {
+            step1 = inverse(sourceCRS.getConversionFromBase());
+        } catch (NoninvertibleTransformException exception) {
+            throw new OperationNotFoundException(notFoundMessage(sourceCRS, targetCRS), exception);
+        }
         return concatenate(step1, step2, step3);
     }
 
@@ -1003,15 +1013,10 @@ public class CoordinateOperationInferenc
     /**
      * Creates the inverse of the given operation.
      */
-    private CoordinateOperation inverse(final SingleOperation op) throws FactoryException
{
+    private CoordinateOperation inverse(final SingleOperation op) throws NoninvertibleTransformException,
FactoryException {
         final CoordinateReferenceSystem sourceCRS = op.getSourceCRS();
         final CoordinateReferenceSystem targetCRS = op.getTargetCRS();
-        MathTransform transform = op.getMathTransform();
-        try {
-            transform = transform.inverse();
-        } catch (NoninvertibleTransformException exception) {
-            throw new OperationNotFoundException(notFoundMessage(targetCRS, sourceCRS), exception);
-        }
+        final MathTransform transform = op.getMathTransform().inverse();
         return createFromMathTransform(properties(INVERSE_OPERATION), targetCRS, sourceCRS,
                 transform, InverseOperationMethod.create(op.getMethod()), null, null);
     }

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrices.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrices.java?rev=1738223&r1=1738222&r2=1738223&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrices.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrices.java
[UTF-8] Fri Apr  8 09:30:25 2016
@@ -29,6 +29,7 @@ import org.apache.sis.util.ComparisonMod
 import org.apache.sis.util.ArgumentChecks;
 import org.apache.sis.util.resources.Errors;
 import org.apache.sis.internal.util.Numerics;
+import org.apache.sis.internal.util.DoubleDouble;
 import org.apache.sis.internal.metadata.AxisDirections;
 import org.apache.sis.internal.referencing.ExtendedPrecisionMatrix;
 
@@ -558,8 +559,9 @@ public final class Matrices extends Stat
      *
      * <p>The given sub-matrix shall have the following properties:</p>
      * <ul>
-     *   <li>The last column contains translation terms, except in the last row.</li>
-     *   <li>The last row often (but not necessarily) contains 0 values except in the
last column.</li>
+     *   <li>The last row often (but not necessarily) contains 0 values everywhere
except in the last column.</li>
+     *   <li>Values in the last column are translation terms, except in the last row.</li>
+     *   <li>All other values are scale or shear terms.</li>
      * </ul>
      *
      * A square matrix complying with the above conditions is often {@linkplain #isAffine(Matrix)
affine},
@@ -607,22 +609,34 @@ public final class Matrices extends Stat
      * @param  firstAffectedOrdinate The lowest index of the affected ordinates.
      * @param  subMatrix The matrix to use for affected ordinates.
      * @param  numTrailingOrdinates Number of trailing ordinates to pass through.
-     * @return A matrix
+     * @return A matrix for the same transform than the given matrix,
+     *         augmented with leading and trailing pass-through coordinates.
      *
      * @see org.apache.sis.referencing.operation.DefaultMathTransformFactory#createPassThroughTransform(int,
MathTransform, int)
      */
     public static MatrixSIS createPassThrough(final int firstAffectedOrdinate,
             final Matrix subMatrix, final int numTrailingOrdinates)
     {
+        ArgumentChecks.ensureNonNull ("subMatrix",             subMatrix);
         ArgumentChecks.ensurePositive("firstAffectedOrdinate", firstAffectedOrdinate);
         ArgumentChecks.ensurePositive("numTrailingOrdinates",  numTrailingOrdinates);
         final int  expansion = firstAffectedOrdinate + numTrailingOrdinates;
-        int sourceDimensions = subMatrix.getNumCol();
+        int sourceDimensions = subMatrix.getNumCol();           // Will become the number
of dimensions later.
         int targetDimensions = subMatrix.getNumRow();
+        /*
+         * Get data from the source matrix, together with the error terms if present.
+         * The 'stride' and 'length' values will be used for computing indices in that array.
+         * The DoubleDouble temporary object is used only if the array contains error terms.
+         */
+        final int      stride  = sourceDimensions;
+        final int      length  = sourceDimensions * targetDimensions;
+        final double[] sources = getExtendedElements(subMatrix);
+        final DoubleDouble transfer = (sources.length > length) ? new DoubleDouble() :
null;
         final MatrixSIS matrix = createZero(targetDimensions-- + expansion,
-                                            sourceDimensions-- + expansion);
+                                            sourceDimensions-- + expansion,
+                                            transfer != null);
         /*
-         * Following code process for upper row to lower row.
+         * Following code processes from upper row to lower row.
          * First, set the diagonal elements on leading new dimensions.
          */
         for (int j=0; j<firstAffectedOrdinate; j++) {
@@ -633,12 +647,14 @@ public final class Matrices extends Stat
          * which are unconditionally stored in the last column.
          */
         final int lastColumn = sourceDimensions + expansion;
-        for (int j=0; j<targetDimensions; j++) {
-            for (int i=0; i<sourceDimensions; i++) {
-                matrix.setElement(firstAffectedOrdinate + j, firstAffectedOrdinate + i, subMatrix.getElement(j,
i));
-            }
-            matrix.setElement(firstAffectedOrdinate + j, lastColumn, subMatrix.getElement(j,
sourceDimensions));
-        }
+        matrix.setElements(sources, length, stride, transfer,
+                0,                     0,                           // Source (row, colum)
+                firstAffectedOrdinate, firstAffectedOrdinate,       // Target (row, column)
+                targetDimensions,      sourceDimensions);           // Number of rows and
columns to copy.
+        matrix.setElements(sources, length, stride, transfer,
+                0,                     sourceDimensions,            // Source (row, colum):
 last column
+                firstAffectedOrdinate, lastColumn,                  // Target (row, column):
part of last column
+                targetDimensions,      1);                          // Copy some rows of
only 1 column.
         /*
          * Set the pseudo-diagonal elements on the trailing new dimensions.
          * 'diff' is zero for a square matrix and non-zero for rectangular matrix.
@@ -652,14 +668,70 @@ public final class Matrices extends Stat
          * this row contains only 0 element except for the last one, which is 1.
          */
         final int lastRow = targetDimensions + expansion;
-        for (int i=0; i<sourceDimensions; i++) {
-            matrix.setElement(lastRow, i + firstAffectedOrdinate, subMatrix.getElement(targetDimensions,
i));
-        }
-        matrix.setElement(lastRow, lastColumn, subMatrix.getElement(targetDimensions, sourceDimensions));
+        matrix.setElements(sources, length, stride, transfer,
+                targetDimensions, 0,                                // Source (row, colum):
 last row
+                lastRow,          firstAffectedOrdinate,            // Target (row, column):
part of last row
+                1,                sourceDimensions);                // Copy some columns
of only 1 row.
+        matrix.setElements(sources, length, stride, transfer,
+                targetDimensions, sourceDimensions,
+                lastRow,          lastColumn,
+                1,                1);
         return matrix;
     }
 
     /**
+     * Returns a matrix with the same content than the given matrix but a different size,
assuming an affine transform.
+     * This method can be invoked for adding or removing the <strong>last</strong>
dimensions of an affine transform.
+     * More specifically:
+     *
+     * <ul class="verbose">
+     *   <li>If the given {@code numCol} is <var>n</var> less than the
number of columns in the given matrix,
+     *       then the <var>n</var> columns <em>before the last column</em>
are removed.
+     *       The last column is left unchanged because it is assumed to contain the translation
terms.</li>
+     *   <li>If the given {@code numCol} is <var>n</var> more than the
number of columns in the given matrix,
+     *       then <var>n</var> columns are inserted <em>before the last
column</em>.
+     *       All values in the new columns will be zero.</li>
+     *   <li>If the given {@code numRow} is <var>n</var> less than the
number of rows in the given matrix,
+     *       then the <var>n</var> rows <em>before the last row</em>
are removed.
+     *       The last row is left unchanged because it is assumed to contain the usual [0
0 0 … 1] terms.</li>
+     *   <li>If the given {@code numRow} is <var>n</var> more than the
number of rows in the given matrix,
+     *       then <var>n</var> rows are inserted <em>before the last row</em>.
+     *       The corresponding offset and scale factors will be 0 and 1 respectively.
+     *       In other words, new dimensions are propagated unchanged.</li>
+     * </ul>
+     *
+     * @param  matrix  the matrix to resize. This matrix will never be changed.
+     * @param  numRow  the new number of rows. This is equal to the desired number of target
dimensions plus 1.
+     * @param  numCol  the new number of columns. This is equal to the desired number of
source dimensions plus 1.
+     * @return a new matrix of the given size, or the given {@code matrix} if no resizing
was needed.
+     */
+    public static Matrix resizeAffine(final Matrix matrix, int numRow, int numCol) {
+        ArgumentChecks.ensureNonNull         ("matrix", matrix);
+        ArgumentChecks.ensureStrictlyPositive("numRow", numRow);
+        ArgumentChecks.ensureStrictlyPositive("numCol", numCol);
+        int srcRow = matrix.getNumRow();
+        int srcCol = matrix.getNumCol();
+        if (numRow == srcRow && numCol == srcCol) {
+            return matrix;
+        }
+        final int      stride  = srcCol;
+        final int      length  = srcCol * srcRow;
+        final double[] sources = getExtendedElements(matrix);
+        final DoubleDouble transfer = (sources.length > length) ? new DoubleDouble() :
null;
+        final MatrixSIS resized = createZero(numRow, numCol, transfer != null);
+        final int copyRow = Math.min(--numRow, --srcRow);
+        final int copyCol = Math.min(--numCol, --srcCol);
+        for (int j=copyRow; j<numRow; j++) {
+            resized.setElement(j, j, 1);
+        }
+        resized.setElements(sources, length, stride, transfer, 0,      0,       0,      0,
      copyRow, copyCol);    // Shear and scale terms.
+        resized.setElements(sources, length, stride, transfer, 0,      srcCol,  0,      numCol,
 copyRow, 1);          // Translation column.
+        resized.setElements(sources, length, stride, transfer, srcRow, 0,       numRow, 0,
      1,       copyCol);    // Last row.
+        resized.setElements(sources, length, stride, transfer, srcRow, srcCol,  numRow, numCol,
 1,       1);          // Last row.
+        return resized;
+    }
+
+    /**
      * Returns {@code true} if the given matrix is likely to use extended precision.
      * A value of {@code true} is not a guarantee that the matrix uses extended precision,
      * but a value of {@code false} is a guarantee that it does not.
@@ -670,6 +742,17 @@ public final class Matrices extends Stat
     }
 
     /**
+     * Returns the elements of the given matrix, together with error terms if available.
+     */
+    private static double[] getExtendedElements(final Matrix matrix) {
+        if (matrix instanceof ExtendedPrecisionMatrix) {
+            return ((ExtendedPrecisionMatrix) matrix).getExtendedElements();
+        } else {
+            return MatrixSIS.castOrCopy(matrix).getElements();
+        }
+    }
+
+    /**
      * Creates a new matrix which is a copy of the given matrix.
      *
      * <div class="note"><b>Implementation note:</b>

Modified: sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/MatrixSIS.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/MatrixSIS.java?rev=1738223&r1=1738222&r2=1738223&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/MatrixSIS.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/MatrixSIS.java
[UTF-8] Fri Apr  8 09:30:25 2016
@@ -249,6 +249,41 @@ public abstract class MatrixSIS implemen
     public abstract void setElements(final double[] elements);
 
     /**
+     * Sets elements in a sub-region of this matrix, optionally including error terms.
+     *
+     * @param source    Row-major values as given by {@link ExtendedPrecisionMatrix#getExtendedElements()}.
+     * @param length    Number of elements ({@code numRow} × {@code numCol}) in the source
matrix, not including error terms.
+     * @param stride    Number of columns in the source matrix, used for computing indices
in {@code source} array.
+     * @param srcRow    Index of the first row from the {@code source} to copy in {@code
this}.
+     * @param srcCol    Index of the first column from the {@code source} to copy in {@code
this}.
+     * @param dstRow    Index of the first row in {@code this} where to copy the {@code source}
values.
+     * @param dstCol    Index of the first column in {@code this} where to copy the {@code
source} values.
+     * @param numRow    Number of rows to copy.
+     * @param numCol    Number of columns to copy.
+     * @param transfer  If both {@code source} and {@code this} use extended precision,
+     *                  the temporary object to use for transferring values. Otherwise {@code
null}.
+     */
+    final void setElements(final double[] source, final int length, final int stride, final
DoubleDouble transfer,
+                           int srcRow, final int srcCol,
+                           int dstRow, final int dstCol,
+                           int numRow, final int numCol)
+    {
+        while (--numRow >= 0) {
+            final int valueOffset = srcRow*stride + srcCol;
+            for (int i=0; i<numCol; i++) {
+                if (transfer != null) {
+                    transfer.setFrom(source, valueOffset + i, length);
+                    set(dstRow, dstCol + i, transfer);
+                } else {
+                    setElement(dstRow, dstCol + i, source[valueOffset + i]);
+                }
+            }
+            srcRow++;
+            dstRow++;
+        }
+    }
+
+    /**
      * Sets this matrix to the values of another matrix.
      * The given matrix must have the same size.
      *

Modified: sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/MatricesTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/MatricesTest.java?rev=1738223&r1=1738222&r2=1738223&view=diff
==============================================================================
--- sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/MatricesTest.java
[UTF-8] (original)
+++ sis/branches/JDK8/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/MatricesTest.java
[UTF-8] Fri Apr  8 09:30:25 2016
@@ -39,7 +39,7 @@ import static org.opengis.referencing.cs
  *
  * @author  Martin Desruisseaux (Geomatys)
  * @since   0.4
- * @version 0.4
+ * @version 0.7
  * @module
  */
 @DependsOn({
@@ -354,16 +354,49 @@ public final strictfp class MatricesTest
         });
         matrix = Matrices.createPassThrough(2, matrix, 1);
         assertEquals(Matrices.create(6, 7, new double[] {
-            1, 0, 0, 0, 0, 0, 0,  // Dimension added
-            0, 1, 0, 0, 0, 0, 0,  // Dimension added
-            0, 0, 2, 0, 3, 0, 8,  // Sub-matrix, row 0
-            0, 0, 0, 4, 7, 0, 5,  // Sub-matrix, row 1
-            0, 0, 0, 0, 0, 1, 0,  // Dimension added
-            0, 0, 0, 0, 0, 0, 1   // Last sub-matrix row
+            1, 0, 0, 0, 0, 0, 0,        // Dimension added
+            0, 1, 0, 0, 0, 0, 0,        // Dimension added
+            0, 0, 2, 0, 3, 0, 8,        // Sub-matrix, row 0
+            0, 0, 0, 4, 7, 0, 5,        // Sub-matrix, row 1
+            0, 0, 0, 0, 0, 1, 0,        // Dimension added
+            0, 0, 0, 0, 0, 0, 1         // Last sub-matrix row
         }), matrix);
     }
 
     /**
+     * Tests {@link Matrices#resizeAffine(Matrix, int, int)}.
+     */
+    @Test
+    public void testResizeAffine() {
+        // Add dimensions
+        MatrixSIS matrix = Matrices.create(3, 4, new double[] {
+            2, 0, 3, 8,
+            0, 4, 7, 5,
+            0, 0, 0, 1
+        });
+        assertEquals(Matrices.create(5, 6, new double[] {
+            2, 0, 3, 0, 0, 8,
+            0, 4, 7, 0, 0, 5,
+            0, 0, 1, 0, 0, 0,
+            0, 0, 0, 1, 0, 0,
+            0, 0, 0, 0, 0, 1
+        }), Matrices.resizeAffine(matrix, 5, 6));
+
+        // Remove dimensions
+        matrix = Matrices.create(4, 5, new double[] {
+            1, 2, 7, 8, 9,
+            3, 4, 6, 7, 8,
+            9, 8, 7, 6, 5,
+            4, 3, 2, 1, -1
+        });
+        assertEquals(Matrices.create(3, 3, new double[] {
+            1, 2, 9,
+            3, 4, 8,
+            4, 3, -1
+        }), Matrices.resizeAffine(matrix, 3, 3));
+    }
+
+    /**
      * Tests {@link MatrixSIS#removeRows(int, int)}
      */
     @Test



Mime
View raw message