+ *
• {@link Double#NaN} values are considered equals to all other NaN values
• + *
• Infinite values are considered equal to other infinite values of the same sign
• + *
• All other values are considered equal if the absolute value of their difference is + * smaller than or equals to the threshold described below.
• + *
+ * + * If {@code relative} is {@code true}, then for any pair of values v1j,i + * and v2j,i to compare, the tolerance threshold is scaled by + * {@code max(abs(v1), abs(v2))}. Otherwise the threshold is used as-is. + * + * @param m1 The first matrix to compare, or {@code null}. + * @param m2 The second matrix to compare, or {@code null}. + * @param epsilon The tolerance value. + * @param relative If {@code true}, then the tolerance value is relative to the magnitude + * of the matrix elements being compared. + * @return {@code true} if the values of the two matrix do not differ by a quantity + * greater than the given tolerance threshold. + * + * @see MatrixSIS#equals(Matrix, double) + */ + public static boolean equals(final Matrix m1, final Matrix m2, final double epsilon, final boolean relative) { + if (m1 != m2) { + if (m1 == null || m2 == null) { + return false; + } + final int numRow = m1.getNumRow(); + if (numRow != m2.getNumRow()) { + return false; + } + final int numCol = m1.getNumCol(); + if (numCol != m2.getNumCol()) { + return false; + } + for (int j=0; j + *
• {@link ComparisonMode#STRICT STRICT}: the two matrices must be of the same + * class, have the same size and the same element values.
• + *
• {@link ComparisonMode#BY_CONTRACT BY_CONTRACT}/{@link ComparisonMode#IGNORE_METADATA + * IGNORE_METADATA}: the two matrices must have the same size and the same element + * values, but are not required to be the same implementation class (any {@link Matrix} + * is okay).
• + *
• {@link ComparisonMode#APPROXIMATIVE APPROXIMATIVE}: the two matrixes must have + * the same size, but the element values can differ up to some threshold. The threshold + * value is determined empirically and may change in future SIS versions.
• + * + * + * @param m1 The first matrix to compare, or {@code null}. + * @param m2 The second matrix to compare, or {@code null}. + * @param mode The strictness level of the comparison. + * @return {@code true} if both matrices are equal. + * + * @see MatrixSIS#equals(Object, ComparisonMode) + */ + public static boolean equals(final Matrix m1, final Matrix m2, final ComparisonMode mode) { + switch (mode) { + case STRICT: return Objects.equals(m1, m2); + case BY_CONTRACT: // Fall through + case IGNORE_METADATA: return equals(m1, m2, 0, false); + case DEBUG: // Fall through + case APPROXIMATIVE: return equals(m1, m2, Numerics.COMPARISON_THRESHOLD, true); + default: throw new IllegalArgumentException(Errors.format(Errors.Keys.UnknownEnumValue_1, mode)); + } + } + + /** + * Returns a unlocalized string representation of the given matrix. + * For each column, the numbers are aligned on the decimal separator. + * + * {@note Formatting on a per-column basis is convenient for the kind of matrices used in referencing by coordinates, + * because each column is typically a displacement vector in a different dimension of the source coordinate + * reference system. In addition, the last column is often a translation vector having a magnitude very + * different than the other columns.} + * + * @param matrix The matrix for which to get a string representation. + * @return A string representation of the given matrix. + */ + public static String toString(final Matrix matrix) { + final int numRow = matrix.getNumRow(); + final int numCol = matrix.getNumCol(); + final String[] elements = new String[numRow * numCol]; + final int[] columnWidth = new int[numCol]; + final int[] maximumFractionDigits = new int[numCol]; + final int[] maximumRemainingWidth = new int[numCol]; // Minus sign (if any) + integer digits + decimal separator + 2 spaces. + int totalWidth = 1; + /* + * Create now the string representation of all matrix elements and measure the width + * of the integer field and the fraction field, then the total width of each column. + */ + for (int i=0; i= 0) { + width = (maximumRemainingWidth[i] = Math.max(maximumRemainingWidth[i], ++s + MARGIN)) + + (maximumFractionDigits[i] = Math.max(maximumFractionDigits[i], width - s)); + } else { + // NaN or Infinity. + width += MARGIN; + } + columnWidth[i] = Math.max(columnWidth[i], width); + } + totalWidth += columnWidth[i]; + } + /* + * Now append the formatted elements with the appropriate amount of spaces + * and trailling zeros for each column. + */ + final String lineSeparator = System.lineSeparator(); + final CharSequence whiteLine = CharSequences.spaces(totalWidth); + final StringBuffer buffer = new StringBuffer((totalWidth + 2 + lineSeparator.length()) * (numRow + 2)); + buffer.append('┌').append(whiteLine).append('┐').append(lineSeparator); + for (int k=0,j=0; j= 0 ? maximumRemainingWidth[i] - ++s : columnWidth[i] - width)).append(element); + s += maximumFractionDigits[i] - width; + while (--s >= 0) { + buffer.append('0'); + } + } + buffer.append(" │").append(lineSeparator); + } + return buffer.append('└').append(whiteLine).append('┘').append(lineSeparator).toString(); + } +} Propchange: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrices.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrices.java ------------------------------------------------------------------------------ svn:mime-type = text/plain;charset=UTF-8 Modified: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/MatrixSIS.java URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/MatrixSIS.java?rev=1521545&r1=1521544&r2=1521545&view=diff ============================================================================== --- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/MatrixSIS.java (original) +++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/MatrixSIS.java Tue Sep 10 16:40:50 2013 @@ -16,30 +16,55 @@ */ package org.apache.sis.referencing.operation.matrix; +import java.io.Serializable; import org.opengis.referencing.operation.Matrix; import org.apache.sis.util.ComparisonMode; import org.apache.sis.util.LenientComparable; +import org.apache.sis.util.resources.Errors; /** * A matrix able to perform some operations of interest to Spatial Information Systems (SIS). - * The GeoAPI {@link Matrix} interface is basically a two dimensional array of numbers. - * The {@code MatrixSIS} class adds some operations. + * This class completes the GeoAPI {@link Matrix} interface with some operations used by {@code sis-referencing}. + * It is not a {@code MatrixSIS} goal to provide all possible Matrix operations, as there is too many of them. + * This class focuses only on: * - *

It is not a {@code MatrixSIS} goal to provide all possible Matrix operations, as there is too many of them. - * This interface focuses only on basic operations needed for referencing by coordinates - * ({@link #negate()}, {@link #transpose()}, {@link #inverse()}, {@link #multiply(Matrix)}), - * completed by some operations more specific to referencing by coordinates - * ({@link #isAffine()}, {@link #normalizeColumns()}).

+ *
+ *