sis-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From desruisse...@apache.org
Subject svn commit: r1529160 - in /sis/branches/JDK7/core/sis-referencing/src: main/java/org/apache/sis/referencing/operation/matrix/ test/java/org/apache/sis/referencing/operation/matrix/
Date Fri, 04 Oct 2013 13:25:48 GMT
Author: desruisseaux
Date: Fri Oct  4 13:25:48 2013
New Revision: 1529160

URL: http://svn.apache.org/r1529160
Log:
Improvement in Matrix string representation for making easier to spot "interesting" values.

Modified:
    sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrices.java
    sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/MatricesTest.java
    sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/Matrix4Test.java

Modified: 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=1529160&r1=1529159&r2=1529160&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrices.java
[UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/main/java/org/apache/sis/referencing/operation/matrix/Matrices.java
[UTF-8] Fri Oct  4 13:25:48 2013
@@ -68,7 +68,7 @@ public final class Matrices extends Stat
     /**
      * Number of spaces to put between columns formatted by {@link #toString(Matrix)}.
      */
-    private static final int MARGIN = 2;
+    private static final int SPACING = 2;
 
     /**
      * Do not allows instantiation of this class.
@@ -830,6 +830,25 @@ public final class Matrices extends Stat
      * Returns a unlocalized string representation of the given matrix.
      * For each column, the numbers are aligned on the decimal separator.
      *
+     * <p>The current implementation formats ±0 and ±1 without trailing {@code ".0"},
and all other values with
+     * a per-column uniform number of fraction digits. The ±0 and ±1 values are treated
especially because they
+     * usually imply a "<cite>no scale</cite>", "<cite>no translation</cite>"
or "<cite>orthogonal axes</cite>"
+     * meaning. A matrix in SIS is often populated mostly by ±0 and ±1 values, with a few
"interesting" values.
+     * The simpler ±0 and ±1 formatting makes easier to spot the "interesting" values.</p>
+     *
+     * <p>The following example shows the string representation of an affine transform
which swap
+     * (<var>latitude</var>, <var>longitude</var>) axes, converts
degrees to radians and converts
+     * height values from feet to metres:</p>
+     *
+     * {@preformat math
+     *   ┌                                                       ┐
+     *   │ 0                     0.017453292519943295  0       0 │
+     *   │ 0.017453292519943295  0                     0       0 │
+     *   │ 0                     0                     0.3048  0 │
+     *   │ 0                     0                     0       1 │
+     *   └                                                       ┘
+     * }
+     *
      * {@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
@@ -841,53 +860,92 @@ public final class Matrices extends Stat
     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.
+        final String[]  elements            = new String [numCol * numRow];
+        final boolean[] noFractionDigits    = new boolean[numCol * numRow];
+        final boolean[] hasDecimalSeparator = new boolean[numCol];
+        final int[] maximumFractionDigits   = new int    [numCol];
+        final int[] widthBeforeFraction     = new int    [numCol]; // spacing + ('-') + integerDigits
+ '.'
+        final int[] columnWidth             = new int    [numCol];
         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.
          */
-        int margin = 1; // Margin before the first column only.
+        int spacing = 1; // Spacing is 1 before the first column only, then SPACING for other
columns.
         for (int i=0; i<numCol; i++) {
             for (int j=0; j<numRow; j++) {
-                final String element = Double.toString(matrix.getElement(j,i)).replace("Infinity",
"∞");
-                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));
+                final int flatIndex = j*numCol + i;
+                final double value  = matrix.getElement(j,i);
+                String element = Double.toString(value);
+                final int width;
+                /*
+                 * Special case for ±0 and ±1 (because those values appear very often and
have
+                 * a particular meaning): for those values, we will ignore the fraction digits.
+                 * For all other values, we will format all fraction digits.
+                 */
+                if (value == -1 || value == 0 || value == +1) {
+                    noFractionDigits[flatIndex] = true;
+                    width = spacing + element.length() - 2; // The -2 is for ignoring the
trailing ".0"
+                    widthBeforeFraction[i] = Math.max(widthBeforeFraction[i], width);
                 } else {
-                    // NaN or Infinity.
-                    width += margin;
+                    /*
+                     * All values other than ±0 and ±1. Store separately the width before
and after
+                     * the decimal separator. The width before the separator contains the
spacing.
+                     */
+                    int s = element.lastIndexOf('.');
+                    if (s >= 0) {
+                        s++; // After the separator.
+                        hasDecimalSeparator[i] = true;
+                        width = (widthBeforeFraction  [i] = Math.max(widthBeforeFraction
 [i], spacing + s))
+                              + (maximumFractionDigits[i] = Math.max(maximumFractionDigits[i],
element.length() - s));
+                    } else {
+                        // NaN or Infinity.
+                        element = element.replace("Infinity", "∞");
+                        width = spacing + element.length();
+                    }
                 }
                 columnWidth[i] = Math.max(columnWidth[i], width);
+                elements[flatIndex] = element;
             }
             totalWidth += columnWidth[i];
-            margin = MARGIN; // Margin before all columns after the first one.
+            spacing = SPACING; // Specing before all columns after the first one.
         }
         /*
-         * Now append the formatted elements with the appropriate amount of spaces
-         * and trailling zeros for each column.
+         * Now append the formatted elements with the appropriate amount of spaces before
each value,
+         * and trailling zeros after each value except ±0, ±1, NaN and infinities.
          */
-        final String lineSeparator = System.lineSeparator();
+        final String   lineSeparator = System.lineSeparator();
         final CharSequence whiteLine = CharSequences.spaces(totalWidth);
-        final StringBuffer buffer = new StringBuffer((totalWidth + 2 + lineSeparator.length())
* (numRow + 2));
+        final StringBuilder   buffer = new StringBuilder((totalWidth + 2 + lineSeparator.length())
* (numRow + 2));
         buffer.append('┌').append(whiteLine).append('┐').append(lineSeparator);
-        for (int k=0,j=0; j<numRow; j++) {
+        int flatIndex = 0;
+        for (int j=0; j<numRow; j++) {
             buffer.append('│');
             for (int i=0; i<numCol; i++) {
-                final String element = elements[k++];
+                final String element = elements[flatIndex];
                 final int width = element.length();
-                int s = element.lastIndexOf('.');
-                buffer.append(CharSequences.spaces(s >= 0 ? maximumRemainingWidth[i] -
++s : columnWidth[i] - width)).append(element);
+                int spaces, s = element.lastIndexOf('.');
+                if (s >= 0) {
+                    if (hasDecimalSeparator[i]) s++;
+                    spaces = widthBeforeFraction[i] - s; // Number of spaces for alignment
on the decimal separator
+                } else {
+                    spaces = columnWidth[i] - width; // Number of spaces for right alignment
(NaN or ∞ cases)
+                }
+                buffer.append(CharSequences.spaces(spaces)).append(element);
+                /*
+                 * Append trailing spaces for ±0 and ±1 values,
+                 * or trailing zeros for all other real values.
+                 */
                 s += maximumFractionDigits[i] - width;
-                while (--s >= 0) {
-                    buffer.append('0');
+                if (noFractionDigits[flatIndex]) {
+                    buffer.setLength(buffer.length() - 2); // Erase the trailing ".0"
+                    buffer.append(CharSequences.spaces(s + 2));
+                } else {
+                    while (--s >= 0) {
+                        buffer.append('0');
+                    }
                 }
+                flatIndex++;
             }
             buffer.append(" │").append(lineSeparator);
         }

Modified: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/MatricesTest.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/MatricesTest.java?rev=1529160&r1=1529159&r2=1529160&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/MatricesTest.java
[UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/MatricesTest.java
[UTF-8] Fri Oct  4 13:25:48 2013
@@ -331,18 +331,28 @@ public final strictfp class MatricesTest
      */
     @Test
     public void testToString() {
-        final MatrixSIS matrix = Matrices.create(4, 4, new double[] {
-            39.5193682106975150,  -68.5200,     80.0,  98,
-           -66.0358637477182200,   Double.NaN,  43.9,  Double.NEGATIVE_INFINITY,
-             2.0741018968776337,   83.7260,     37.0,  -3,
-            91.8796187759200600,  -18.2674,     24.0,  36
+        assertMultilinesEquals(
+                "┌            ┐\n" +
+                "│ 1  0  0  0 │\n" +
+                "│ 0  1  0  0 │\n" +
+                "│ 0  0  1  0 │\n" +
+                "│ 0  0  0  1 │\n" +
+                "└            ┘\n", new Matrix4().toString());
+        /*
+         * Mix of values with different precision, ±0, ±1, NaN and infinities.
+         */
+        final MatrixSIS matrix = Matrices.create(4, 5, new double[] {
+            39.5193682106975150,  -68.5200,     -1.0,  1,  98,
+           -66.0358637477182200,   Double.NaN,  43.0,  0,  Double.NEGATIVE_INFINITY,
+             2.0741018968776337,   83.7260,     -0.0,  1,  -3,
+            91.8796187759200600,  -18.2674,     24.5,  0,  36.5
         });
         assertMultilinesEquals(
-                "┌                                            ┐\n" +
-                "│  39.5193682106975150  -68.5200  80.0  98.0 │\n" +
-                "│ -66.0358637477182200       NaN  43.9    -∞ │\n" +
-                "│   2.0741018968776337   83.7260  37.0  -3.0 │\n" +
-                "│  91.8796187759200600  -18.2674  24.0  36.0 │\n" +
-                "└                                            ┘\n", matrix.toString());
+                "┌                                               ┐\n" +
+                "│  39.5193682106975150  -68.5200  -1    1  98.0 │\n" +
+                "│ -66.0358637477182200       NaN  43.0  0    -∞ │\n" +
+                "│   2.0741018968776337   83.7260  -0    1  -3.0 │\n" +
+                "│  91.8796187759200600  -18.2674  24.5  0  36.5 │\n" +
+                "└                                               ┘\n", matrix.toString());
     }
 }

Modified: sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/Matrix4Test.java
URL: http://svn.apache.org/viewvc/sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/Matrix4Test.java?rev=1529160&r1=1529159&r2=1529160&view=diff
==============================================================================
--- sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/Matrix4Test.java
[UTF-8] (original)
+++ sis/branches/JDK7/core/sis-referencing/src/test/java/org/apache/sis/referencing/operation/matrix/Matrix4Test.java
[UTF-8] Fri Oct  4 13:25:48 2013
@@ -112,9 +112,6 @@ public final strictfp class Matrix4Test 
         final MatrixSIS step3 = step2.multiply(step1).inverse();
         /*
          * Concatenate everything, which should go back to the identity transform.
-         * We have a slight residu in the longitude translation term because of the
-         * prime meridian shift - we will set this residu to zero for this test.
-         *
          * Note that the 'isIdentity()' test fail if the double-double arithmetic is
          * disabled, because some scale factors will be 0.9999999999999999 instead of 1.
          */



Mime
View raw message