sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1521545 - in /sis/branches/JDK7/core: sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/ sis-utility/src/main/java/org/apache/sis/util/resources/
Date Tue, 10 Sep 2013 16:40:51 GMT
Author: desruisseaux
Date: Tue Sep 10 16:40:50 2013
New Revision: 1521545

URL: http://svn.apache.org/r1521545
Log:
Make MatrixSIS an abstract class instead than an interface, and partial port of Matrices utility
class. 

Added:
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrices.java
  (with props)
Modified:
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/MatrixSIS.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
    sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties

Added: sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrices.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrices.java?rev=1521545&view=auto
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrices.java
(added)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrices.java
[UTF-8] Tue Sep 10 16:40:50 2013
@@ -0,0 +1,209 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.sis.referencing.operation.matrix;
+
+import org.opengis.referencing.operation.Matrix;
+import org.apache.sis.util.Static;
+import org.apache.sis.util.CharSequences;
+import org.apache.sis.util.ComparisonMode;
+import org.apache.sis.util.resources.Errors;
+import org.apache.sis.internal.util.Numerics;
+
+// Related to JDK7
+import java.util.Objects;
+
+
+/**
+ * Static utility methods for creating and manipulating {@link Matrix} instances.
+ *
+ * @author  Martin Desruisseaux (IRD, Geomatys)
+ * @since   0.4 (derived from geotk-2.2)
+ * @version 0.4
+ * @module
+ */
+public final class Matrices extends Static {
+    /**
+     * Number of spaces to put between columns formatted by {@link #toString(Matrix)}.
+     */
+    private static final int MARGIN = 2;
+
+    /**
+     * Do not allows instantiation of this class.
+     */
+    private Matrices() {
+    }
+
+    /**
+     * Compares the given matrices for equality, using the given relative or absolute tolerance
threshold.
+     * The matrix elements are compared as below:
+     *
+     * <ul>
+     *   <li>{@link Double#NaN} values are considered equals to all other NaN values</li>
+     *   <li>Infinite values are considered equal to other infinite values of the same
sign</li>
+     *   <li>All other values are considered equal if the absolute value of their difference
is
+     *       smaller than or equals to the threshold described below.</li>
+     * </ul>
+     *
+     * If {@code relative} is {@code true}, then for any pair of values <var>v1</var><sub>j,i</sub>
+     * and <var>v2</var><sub>j,i</sub> 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<numRow; j++) {
+                for (int i=0; i<numCol; i++) {
+                    final double v1 = m1.getElement(j, i);
+                    final double v2 = m2.getElement(j, i);
+                    double tolerance = epsilon;
+                    if (relative) {
+                        tolerance *= Math.max(Math.abs(v1), Math.abs(v2));
+                    }
+                    if (!(Math.abs(v1 - v2) <= tolerance)) {
+                        if (Numerics.equals(v1, v2)) {
+                            // Special case for NaN and infinite values.
+                            continue;
+                        }
+                        return false;
+                    }
+                }
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Compares the given matrices for equality, using the given comparison strictness level.
+     * To be considered equal, the two matrices must meet the following conditions, which
depend
+     * on the {@code mode} argument:
+     *
+     * <ul>
+     *   <li><b>{@link ComparisonMode#STRICT STRICT}:</b> the two matrices
must be of the same
+     *       class, have the same size and the same element values.</li>
+     *   <li><b>{@link ComparisonMode#BY_CONTRACT BY_CONTRACT}/{@link ComparisonMode#IGNORE_METADATA
+     *       IGNORE_METADATA}:</b> 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).</li>
+     *   <li><b>{@link ComparisonMode#APPROXIMATIVE APPROXIMATIVE}:</b>
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.</li>
+     * </ul>
+     *
+     * @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<numCol; i++) {
+            for (int j=0; j<numRow; j++) {
+                final String element = Double.toString(matrix.getElement(j,i));
+                elements[j*numCol + i] = element;
+                int width = element.length();
+                int s = element.lastIndexOf('.');
+                if (s >= 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<numRow; j++) {
+            buffer.append('│');
+            for (int i=0; i<numCol; i++) {
+                final String element = elements[k++];
+                final int width = element.length();
+                int s = element.lastIndexOf('.');
+                buffer.append(CharSequences.spaces(s >= 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:
  *
- * <p>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 <cite>referencing by
coordinates</cite>
- * ({@link #negate()}, {@link #transpose()}, {@link #inverse()}, {@link #multiply(Matrix)}),
- * completed by some operations more specific to referencing by coordinates
- * ({@link #isAffine()}, {@link #normalizeColumns()}).</p>
+ * <ul>
+ *   <li>basic operations needed for <cite>referencing by coordinates</cite>:
+ *       {@link #negate()}, {@link #transpose()}, {@link #inverse()}, {@link #multiply(Matrix)};</li>
+ *   <li>some operations more specific to referencing by coordinates:
+ *       {@link #isAffine()}, {@link #normalizeColumns()}.</li>
+ * </ul>
  *
  * @author  Martin Desruisseaux (IRD, Geomatys)
  * @since   0.4 (derived from geotk-2.2)
  * @version 0.4
  * @module
- *
- * @see Matrices#toSIS(Matrix)
  */
-public interface MatrixSIS extends Matrix, LenientComparable {
+public abstract class MatrixSIS implements Matrix, LenientComparable, Cloneable, Serializable
{
+    /**
+     * For cross-version compatibility.
+     */
+    private static final long serialVersionUID = 3075280376118406219L;
+
+    /**
+     * For sub-class constructors.
+     */
+    protected MatrixSIS() {
+    }
+
+    /**
+     * Ensures that the given matrix is a square matrix having 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) {
+            throw new MismatchedMatrixSizeException(Errors.format(Errors.Keys.MismatchedMatrixSize_2,
numRow, numCol));
+        }
+    }
+
     /**
      * Returns {@code true} if this matrix represents an affine transform.
      * A transform is affine if the matrix is square and its last row contains
@@ -47,7 +72,18 @@ public interface MatrixSIS extends Matri
      *
      * @return {@code true} if this matrix is affine.
      */
-    boolean isAffine();
+    public abstract boolean isAffine();
+
+    /**
+     * Returns {@code true} if this matrix is an identity matrix.
+     *
+     * @return {@code true} if this matrix is an identity matrix.
+     *
+     * @see #setToIdentity()
+     * @see java.awt.geom.AffineTransform#isIdentity()
+     */
+    @Override
+    public abstract boolean isIdentity();
 
     /**
      * Returns {@code true} if this matrix is close to an identity matrix, given a tolerance
threshold.
@@ -57,34 +93,33 @@ public interface MatrixSIS extends Matri
      *
      * @param  tolerance The tolerance value, or 0 for a strict comparison.
      * @return {@code true} if this matrix is close to the identity matrix given the tolerance
threshold.
-     *
-     * @see java.awt.geom.AffineTransform#isIdentity()
      */
-    boolean isIdentity(double tolerance);
+    public abstract boolean isIdentity(double tolerance);
 
     /**
      * Sets this matrix to zero everywhere except for the elements on the diagonal, which
are set to 1.
      * If this matrix contains more rows than columns, then the extra rows will contain only
zero values.
      * If this matrix contains more columns than rows, then the extra columns will contain
only zero values.
      *
+     * @see #isIdentity()
      * @see java.awt.geom.AffineTransform#setToIdentity()
      */
-    void setToIdentity();
+    public abstract void setToIdentity();
 
     /**
      * Sets all the values in this matrix to zero.
      */
-    void setToZero();
+    public abstract void setToZero();
 
     /**
      * Negates the values of this matrix: {@code this} = {@code -this}.
      */
-    void negate();
+    public abstract void negate();
 
     /**
      * Sets the value of this matrix to its transpose.
      */
-    void transpose();
+    public abstract void transpose();
 
     /**
      * Normalizes all columns in-place. Each columns in this matrix is considered as a vector.
@@ -98,7 +133,7 @@ public interface MatrixSIS extends Matri
      * ordinate in the source space is increased by one. Invoking this method turns those
vectors
      * into unitary vectors, which is useful for forming the basis of a new coordinate system.</p>
      */
-    void normalizeColumns();
+    public abstract void normalizeColumns();
 
     /**
      * Returns a new matrix which is the result of multiplying this matrix with the specified
one.
@@ -113,15 +148,17 @@ public interface MatrixSIS extends Matri
      * @throws MismatchedMatrixSizeException if the number of rows in the given matrix is
not equals to the
      *         number of columns in this matrix.
      */
-    MatrixSIS multiply(Matrix matrix) throws MismatchedMatrixSizeException;
+    public abstract MatrixSIS multiply(Matrix matrix) throws MismatchedMatrixSizeException;
 
     /**
      * Returns the inverse of this matrix.
      *
      * @return The inverse of this matrix.
      * @throws SingularMatrixException if this matrix is not invertible.
+     *
+     * @see java.awt.geom.AffineTransform#createInverse()
      */
-    MatrixSIS inverse() throws SingularMatrixException;
+    public abstract MatrixSIS inverse() throws SingularMatrixException;
 
     /**
      * Compares the given matrices for equality, using the given absolute tolerance threshold.
@@ -141,7 +178,9 @@ public interface MatrixSIS extends Matri
      *
      * @see Matrices#equals(Matrix, Matrix, double, boolean)
      */
-    boolean equals(Matrix matrix, double tolerance);
+    public boolean equals(final Matrix matrix, final double tolerance) {
+        return Matrices.equals(this, matrix, tolerance, false);
+    }
 
     /**
      * Compares this matrix with the given object for equality. To be considered equal, the
two
@@ -165,7 +204,9 @@ public interface MatrixSIS extends Matri
      * @see Matrices#equals(Matrix, Matrix, ComparisonMode)
      */
     @Override
-    boolean equals(Object object, ComparisonMode mode);
+    public boolean equals(final Object object, final ComparisonMode mode) {
+        return (object instanceof Matrix) && Matrices.equals(this, (Matrix) object,
mode);
+    }
 
     /**
      * Returns a clone of this matrix.
@@ -173,5 +214,22 @@ public interface MatrixSIS extends Matri
      * @return A new matrix of the same class and with the same values than this matrix.
      */
     @Override
-    MatrixSIS clone();
+    public MatrixSIS clone() {
+        try {
+            return (MatrixSIS) super.clone();
+        } catch (CloneNotSupportedException e) {
+            throw new AssertionError(e); // Should never happen, since we are cloneable.
+        }
+    }
+
+    /**
+     * Returns a unlocalized string representation of this matrix.
+     * For each column, the numbers are aligned on the decimal separator.
+     *
+     * @see Matrices#toString(Matrix)
+     */
+    @Override
+    public String toString() {
+        return Matrices.toString(this);
+    }
 }

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java?rev=1521545&r1=1521544&r2=1521545&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
[UTF-8] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.java
[UTF-8] Tue Sep 10 16:40:50 2013
@@ -336,6 +336,11 @@ public final class Errors extends Indexe
         public static final int MismatchedDimension_3 = 58;
 
         /**
+         * Matrix can not be of size {0}×{1}.
+         */
+        public static final int MismatchedMatrixSize_2 = 118;
+
+        /**
          * This operation requires the “{0}” module.
          */
         public static final int MissingRequiredModule_1 = 84;

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties?rev=1521545&r1=1521544&r2=1521545&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
[ISO-8859-1] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors.properties
[ISO-8859-1] Tue Sep 10 16:40:50 2013
@@ -78,6 +78,7 @@ MismatchedArrayLengths          = Mismat
 MismatchedCRS                   = The coordinate reference system must be the same for all
objects.
 MismatchedDimension_2           = Mismatched object dimension: {0}D and {1}D.
 MismatchedDimension_3           = Argument \u2018{0}\u2019 has {2} dimension{2,choice,1#|2#s},
while {1} was expected.
+MismatchedMatrixSize_2          = Matrix can not be of size {0}\u00d7{1}.
 MissingRequiredModule_1         = This operation requires the \u201c{0}\u201d module.
 MissingSchemeInURI              = Missing scheme in URI.
 MissingValueForOption_1         = Missing value for option \u201c{0}\u201d.

Modified: sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties?rev=1521545&r1=1521544&r2=1521545&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
[ISO-8859-1] (original)
+++ sis/branches/JDK7/core/sis-utility/src/main/java/org/apache/sis/util/resources/Errors_fr.properties
[ISO-8859-1] Tue Sep 10 16:40:50 2013
@@ -68,6 +68,7 @@ MismatchedArrayLengths          = Les di
 MismatchedCRS                   = Le syst\u00e8me de r\u00e9f\u00e9rence des coordonn\u00e9es
doit \u00eatre le m\u00eame pour tous les objets.
 MismatchedDimension_2           = Les dimensions des objets ({0}D et {1}D) ne concordent
pas.
 MismatchedDimension_3           = L\u2019argument \u2018{0}\u2019 a {2} dimension{2,choice,1#|2#s},
alors qu\u2019on en attendait {1}.
+MismatchedMatrixSize_2          = La matrice ne peut pas \u00eatre de taille {0}\u00d7{1}.
 MissingRequiredModule_1         = Cette op\u00e9ration requiert le module \u201c{0}\u201d.
 MissingSchemeInURI              = Il manque le sch\u00e9ma d\u2019URI.
 MissingValueForOption_1         = Aucune valeur n\u2019a \u00e9t\u00e9 d\u00e9finie pour
l\u2019option \u201c{0}\u201d.



Mime
View raw message