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